测试变量是否为列表或元组

时间:2010-02-02 15:00:24

标签: python types list

在python中,测试变量是否包含列表或元组的最佳方法是什么? (即一个集合)

这是不是像这里建议的那样邪恶? http://www.canonical.org/~kragen/isinstance/

更新:我想要将列表与字符串区分开来的最常见原因是当我有一些无限深度的嵌套树/数据结构列表中的字符串列表等列表时,我正在使用递归算法进行探索我需要知道何时击中“叶子”节点。

13 个答案:

答案 0 :(得分:477)

if type(x) is list:
    print 'a list'
elif type(x) is tuple:
    print 'a tuple'
else:
    print 'neither a tuple or a list'

答案 1 :(得分:87)

如果需要,请继续使用isinstance。它有点邪恶,因为它排除了您可能实际需要的自定义序列,迭代器和其他内容。但是,如果某人(例如)传递了一个字符串,有时您需要采取不同的行为。我倾向于明确检查strunicode,如下所示:

import types
isinstance(var, types.StringTypes)

N.B。不要将types.StringType误认为types.StringTypes。后者包含strunicode个对象。

types模块被许多人认为是过时的,只是直接检查对象的类型,所以如果你不想使用上面的内容,你可以选择性地检查strunicode,像这样:

isinstance(var, (str, unicode)):

修改

更好的是:

isinstance(var, basestring)

结束修改

在其中任何一个之后,您可以回归到表现为正常序列,让非序列引发适当的异常。

看到关于类型检查的“邪恶”的事情并不是你可能想要对某种类型的对象采取不同的行为,而是你人为地限制你的函数使用意外的对象类型来做正确的事情正确的事。如果您的最终回退未经过类型检查,则会删除此限制。应该注意的是,过多的类型检查是代码味道,表明您可能想要进行一些重构,但这并不一定意味着您应该从getgo中避免它。

答案 2 :(得分:37)

使用isinstance没有任何问题,只要它不是多余的。如果变量应该只是一个列表/元组,那么记录接口并只使用它。否则,检查是完全合理的:

if isinstance(a, collections.Iterable):
    # use as a container
else:
    # not a container!

这种类型的检查确实有一些很好的用例,例如使用标准字符串startswith / endswith方法(尽管准确无误,但这些是在CPython中使用显式检查在C中实现的看看它是否是一个元组 - 解决这个问题的方法不止一种,正如你链接的文章所述。

显式检查通常比尝试将对象用作容器并处理异常更好 - 这可能导致代码部分或不必要地运行的各种问题。

答案 3 :(得分:14)

将参数记录为需要作为序列,并将其用作序列。不要检查类型。

答案 4 :(得分:9)

怎么样:hasattr(a, "__iter__")

它告诉返回的对象是否可以作为生成器迭代。默认情况下,元组和列表可以,但不能是字符串类型。

答案 5 :(得分:9)

在Python 2.8 type(list) is list上返回false
我建议用这种可怕的方式比较这种类型:

if type(a) == type([]) :
  print "variable a is a list"

(至少在我的系统上,在Mac OS X Yosemite上使用anaconda)

答案 6 :(得分:8)

Python使用“Duck typing”,即如果变量kwaks像鸭子,它必须是鸭子。在您的情况下,您可能希望它是可迭代的,或者您想要访问某个索引处的项目。你应该这样做:即使用for var:中的var[idx]try块内的{{1}}对象,如果你得到例外,它就不是鸭子......

答案 7 :(得分:6)

>>> l = []
>>> l.__class__.__name__ in ('list', 'tuple')
True

答案 8 :(得分:3)

如果您只需要知道是否可以对变量使用foo[123]表示法,则可以检查是否存在__getitem__属性(当您通过索引访问时,python会调用该属性)与hasattr(foo, '__getitem__')

答案 9 :(得分:1)

原则上,我同意上面的Ignacio,但您也可以使用 type 来检查某些内容是元组还是列表。

>>> a = (1,)
>>> type(a)
(type 'tuple')
>>> a = [1]
>>> type(a)
(type 'list')

答案 10 :(得分:1)

如果您真的想要处理任何函数参数,那么必须进行更复杂的测试。

type(a) != type('') and hasattr(a, "__iter__")

虽然通常仅仅说出一个函数需要迭代然后只检查type(a) != type('')就足够了。

也可能会发生这样的情况:对于一个字符串,你有一个简单的处理路径,或者你会很好并做分裂等,所以你不想对字符串大喊大叫,如果有人发给你一些奇怪的东西,让他有一个例外。

答案 11 :(得分:0)

找出变量是列表或元组还是通常检查变量类型的另一种简便方法是:

    def islist(obj):

        if ("list" in str(type(obj)) ): return True

        else : return False

答案 12 :(得分:0)

不是最优雅的,但是我可以做到(对于Python 3):

if hasattr(instance, '__iter__') and not isinstance(instance, (str, bytes)):
    ...

这允许其他可迭代项(例如Django查询集),但不包括字符串和字节串。我通常在接受单个对象ID或对象ID列表的函数中使用它。有时对象ID可以是字符串,而我不想逐个字符地遍历这些字符。 :)