关于python:测试变量是列表还是元组

Test if a variable is a list or tuple

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

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

更新:我想区分列表和字符串的最常见原因是,当我有一些无限深的嵌套树/数据结构,如字符串列表列表列表等,我正在用递归算法进行探索,我需要知道什么时候碰到了"叶"节点。


1
2
3
4
5
6
if type(x) is list:
    print 'a list'
elif type(x) is tuple:
    print 'a tuple'
else:
    print 'neither a tuple or a list'


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

1
2
import types
isinstance(var, types.StringTypes)

注意,不要把types.StringType误认为types.StringTypes。后者合并了strunicode对象。

许多人认为,types模块已经过时,而只需直接检查对象的类型,因此,如果您不想使用上述模块,您也可以对strunicode进行明确检查,如下所示:

1
isinstance(var, (str, unicode)):

编辑:

更好的是:

1
isinstance(var, basestring)

结束编辑

在这两种情况下,您都可以像获得正常序列一样返回到行为,让非序列引发适当的异常。

请看,类型检查的"邪恶"之处并不是您可能希望对某个特定类型的对象采取不同的行为,而是您人为地限制了您的函数,使其无法使用意外的对象类型来执行正确的操作,否则将执行正确的操作。如果最终回退未选中类型,则删除此限制。应该注意的是,过多的类型检查是一种代码味道,它表明您可能想要进行一些重构,但这并不一定意味着您应该从getgo中避免进行重构。


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

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

这种类型的检查确实有一些很好的用例,例如标准的字符串startswith/endswith方法(尽管为了准确起见,这些方法是在cpython的C中实现的,使用显式检查来查看它是否是元组——有多种方法可以解决这个问题,如您所链接到的文章中所提到的)。

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


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


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

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

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


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

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


python使用"duck-typing",也就是说,如果变量kwak与duck类似,那么它一定是duck。在您的情况下,您可能希望它是可iterable的,或者希望在某个索引处访问该项。你应该这样做:即使用for var:var[idx]中的对象在try块中,如果你得到一个例外,它不是一只鸭子……


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

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


如果您真的想把任何东西作为函数参数来处理,那么必须进行更复杂的测试。

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

不过,通常只需说明一个函数期望它是可执行的,然后只检查type(a) != type('')

另外,对于一个字符串,你可能有一个简单的处理路径,或者你会很好地进行拆分等,所以你不想对字符串大喊大叫,如果有人给你发送了一些奇怪的东西,就让他有一个例外。


原则上,我同意上面的ignacio,但是您也可以使用type来检查某个东西是元组还是列表。

1
2
3
4
5
6
>>> a = (1,)
>>> type(a)
(type 'tuple')
>>> a = [1]
>>> type(a)
(type 'list')


另一种简单的方法是确定变量是列表变量还是元组变量,或者通常检查变量类型:

1
2
3
4
5
    def islist(obj):

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

        else : return False