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/

Reply via email to