On Fri, Aug 14, 2020 at 10:43:31AM +0200, Marco Sulla wrote: > Many times I want a function parameter that is an iterable but not a > string. Usually I do: > > try: > var.__iter__ > except AttributeError: > # not an iterable > else: > try: > var.isascii > except AttributeError: > # put yuour code here
That's buggy. Your test for `var.__iter__` has false positives and false negatives: False positives: if an *instance* (but not the class) happens to have an attribute called `__iter__` your test will think it is iterable when it is not. py> class Demo: ... pass ... py> obj = Demo() py> obj.__iter__ = lambda: iter('abc') py> iter(obj) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'Demo' object is not iterable Remember that dunder methods are only called on the class, not on the instance. False negatives: if your class is indexable and obeys the sequence iteration protocol, then it is iterable, but your test will think it is not: py> class Demo: ... def __getitem__(self, i): ... if i > 5: raise IndexError ... return i**2 ... py> list(Demo()) [0, 1, 4, 9, 16, 25] The best and most reliable way to check if something is iterable is to ask iter: try: iter(obj) except TypeError: # not iterable Alas, the Iterable abc does not recognise the sequence iteration protocol, so `isinstance(obj, Iterable)` fails too. Your test for stringness is also buggy: you have no guarantee that an object with an "isascii" attribute is a string. It will give a false positive to any object with an attribute of that name, even if it isn't a method. Why not just test for `isinstance(obj, str)`? (Does anyone care about UserStr?) -- Steven _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/HXHJDIJTUTKJIZK2SYQDVE3G5VFCOJ23/ Code of Conduct: http://python.org/psf/codeofconduct/