这是我通常所做的,以确定输入是一个列表/元组-而不是一个str。因为很多次我偶然发现错误,其中一个函数错误地传递了一个str对象,而目标函数在lst中执行x,假设lst实际上是一个列表或元组。

assert isinstance(lst, (list, tuple))

我的问题是:有没有更好的方法来实现这个目标?


当前回答

str对象没有__iter__属性

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

你可以检查一下

assert hasattr(x, '__iter__')

这也会对任何其他不可迭代对象抛出一个漂亮的AssertionError。

编辑: 正如Tim在评论中提到的,这只适用于python2。X,不是3。X

其他回答

duck-typing的另一个版本,用于帮助区分类似字符串的对象和其他类似序列的对象。

类字符串对象的字符串表示就是字符串本身,所以你可以检查你是否从str构造函数返回了一个相等的对象:

# If a string was passed, convert it to a single-element sequence
if var == str(var):
    my_list = [var]

# All other iterables
else: 
    my_list = list(var)

这应该适用于所有与str兼容的对象和所有类型的可迭代对象。

Python 3有这个:

from typing import List

def isit(value):
    return isinstance(value, List)

isit([1, 2, 3])  # True
isit("test")  # False
isit({"Hello": "Mars"})  # False
isit((1, 2))  # False

因此,要检查list和tuple,它将是:

from typing import List, Tuple

def isit(value):
    return isinstance(value, List) or isinstance(value, Tuple)

为了提高可读性和最佳实践,请尝试以下方法:

python - 2 - isce ()

import types
if isinstance(lst, types.ListType) or isinstance(lst, types.TupleType):
    # Do something

Python3 - isinstance()

import typing
if isinstance(lst, typing.List) or isinstance(lst, typing.Tuple):
    # Do something

希望能有所帮助。

我在测试用例中这样做。

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))

没有在发电机上进行测试,我认为如果通过发电机,你会在下一次“屈服”时留下,这可能会把下游的事情搞砸。不过,这是一个unittest

在python中>3.6

import collections
isinstance(set(),collections.abc.Container)
True
isinstance([],collections.abc.Container)
True
isinstance({},collections.abc.Container)
True
isinstance((),collections.abc.Container)
True
isinstance(str,collections.abc.Container)
False