How to check if X-quacks are like list / tuple

How do we check if X-quacks are like a list / tuple?

By that, I mean we can multiply it by 0 and 1 (etc.), although it cannot be a string (which can also be a subset).

I thought to test hasattr(X, '__iter__')

and not isinstance(X, str)

, but that would mean that the dictionary will still pass, which I don't want to. Then you can also check that it is not a dictionary, but I would not be so sure about the meanness of dicts etc.

Is there a more official way to check that something does the same as a list or tuple according to this simple specification?

eg. a valid input must be:

'emailaddr' --> ('emailaddr', 'emailaddr')
('emailaddr', 'alias')
['emailaddr', 'alias']
SequenceThing('emailaddr', 'alias')

      

+3


source to share


4 answers


Do you want to check if the value is sequence ?

An iterable that supports efficient access to an element using integer indices using the special getitem () method and defines a len () method that returns the length of the sequence. Some built-in sequence types are list, str, tuple, and bytes. Note that dict also supports getitem () and len (), but is considered a match rather than a sequence because the searches use arbitrary immutable keys rather than integers.

Old way (deprecated in 2.7):

import operator
print operator.isSequenceType(x)

      



New way:

import collections
print isinstance(x, collections.Sequence)

      

They are not equivalent - the latter are more precise, but user-defined types must be registered with it.

In addition, strings are sequences according to both definitions. You can use basestring

specifically.

+2


source


Don't allow a bare line as an argument; this is a special case waiting to bite you. Instead, document that the input must be a tuple / list / whatever, but the second element is optional. I.e

['emailaddr', ]
('emailaddr', )
SequenceThing('emailaddr')

      

are legal but not



'emailaddr'

      

So your function might assume it X[0]

would be an email address, or it X[1]

might exist and be an alias, but that's a user's problem if they supply anything else.

+2


source


Duck printing means that you just want you to want it, and if it doesn't work then you are not dealing with duck.

If you don't specifically want to get strings, check for strings and throw an exception.

And then do whatever you want without type checking.

+1


source


Solution based on Kevin's helpful comment:

>>> import collections
>>> isinstance([], collections.Sequence) and not isinstance([], str)
True
>>> isinstance((), collections.Sequence) and not isinstance((), str)
True
>>> isinstance('', collections.Sequence) and not isinstance('', str)
False
>>> isinstance({}, collections.Sequence) and not isinstance({}, str)
False
>>> isinstance(set(), collections.Sequence) and not isinstance(set(), str)
False

      

Mappings such as dicts and sets will fail the first test. There will be lines, but they will obviously fail in the second test.

0


source







All Articles