How to check if an object is a list or tuple (but

2019-01-04 15:51发布

This is what I normally do in order to ascertain that the input is a list/tuple - but not a str. Because many times I stumbled upon bugs where a function passes a str object by mistake, and the target function does for x in lst assuming that lst is actually a list or tuple.

assert isinstance(lst, (list, tuple))

My question is: is there a better way of achieving this?

16条回答
狗以群分
2楼-- · 2019-01-04 15:59

I do this in my testcases.

def assertIsIterable(self, item):
    #add types here you don't want to mistake as iterables
    if isinstance(item, basestring): 
        raise AssertionError("type %s is not iterable" % type(item))

    #Fake an iteration.
    try:
        for x in item:
            break;
    except TypeError:
        raise AssertionError("type %s is not iterable" % type(item))

Untested on generators, I think you are left at the next 'yield' if passed in a generator, which may screw things up downstream. But then again, this is a 'unittest'

查看更多
爷、活的狠高调
3楼-- · 2019-01-04 16:02

The str object doesn't have an __iter__ attribute

>>> hasattr('', '__iter__')
False 

so you can do a check

assert hasattr(x, '__iter__')

and this will also raise a nice AssertionError for any other non-iterable object too.

Edit: As Tim mentions in the comments, this will only work in python 2.x, not 3.x

查看更多
Anthone
4楼-- · 2019-01-04 16:03
H = "Hello"

if type(H) is list or type(H) is tuple:
    ## Do Something.
else
    ## Do Something.
查看更多
SAY GOODBYE
5楼-- · 2019-01-04 16:04

In python 2 only (not python 3):

assert not isinstance(lst, basestring)

Is actually what you want, otherwise you'll miss out on a lot of things which act like lists, but aren't subclasses of list or tuple.

查看更多
在下西门庆
6楼-- · 2019-01-04 16:05

Python with PHP flavor:

def is_array(var):
    return isinstance(var, (list, tuple))
查看更多
爷的心禁止访问
7楼-- · 2019-01-04 16:06

Generally speaking, the fact that a function which iterates over an object works on strings as well as tuples and lists is more feature than bug. You certainly can use isinstance or duck typing to check an argument, but why should you?

That sounds like a rhetorical question, but it isn't. The answer to "why should I check the argument's type?" is probably going to suggest a solution to the real problem, not the perceived problem. Why is it a bug when a string is passed to the function? Also: if it's a bug when a string is passed to this function, is it also a bug if some other non-list/tuple iterable is passed to it? Why, or why not?

I think that the most common answer to the question is likely to be that developers who write f("abc") are expecting the function to behave as though they'd written f(["abc"]). There are probably circumstances where it makes more sense to protect developers from themselves than it does to support the use case of iterating across the characters in a string. But I'd think long and hard about it first.

查看更多
登录 后发表回答