在python中,测试变量是否包含列表或元组的最佳方法是什么?(即。一组)
isinstance()是否如这里所建议的那样邪恶?http://www.canonical.org/~kragen/isinstance/
更新:我想要区分列表和字符串的最常见原因是,当我有一些无限深嵌套的字符串列表的列表的列表的树/数据结构时,我正在用递归算法探索,我需要知道什么时候我已经碰到了“叶”节点。
在python中,测试变量是否包含列表或元组的最佳方法是什么?(即。一组)
isinstance()是否如这里所建议的那样邪恶?http://www.canonical.org/~kragen/isinstance/
更新:我想要区分列表和字符串的最常见原因是,当我有一些无限深嵌套的字符串列表的列表的列表的树/数据结构时,我正在用递归算法探索,我需要知道什么时候我已经碰到了“叶”节点。
当前回答
你知道的…我这么做可能有点蠢,但我是这么做的
try:
len(thing)
except:
# not a list
如果我能知道它的长度,那肯定不止一件事。
编辑:刚刚意识到,如果非列表项是字符串(因为字符串本质上是字符列表),它将不起作用。
其他回答
使用isinstance没有任何问题,只要它不是多余的。如果一个变量应该只是一个列表/元组,那么就记录接口并这样使用它。否则,检查是完全合理的:
if isinstance(a, collections.abc.Iterable):
# use as a container
else:
# not a container!
这种类型的检查确实有一些很好的用例,比如标准字符串startswith / endswith方法(尽管准确地说,这些方法是在CPython中使用显式检查来实现的,以确定它是否是一个元组——解决这个问题的方法不止一种,正如你链接到的文章中提到的那样)。
显式检查通常比试图将对象用作容器并处理异常更好——后者可能导致代码部分或不必要地运行的各种问题。
在Python 2.8中,type(list) is list返回false 我建议用这种可怕的方式进行比较:
if type(a) == type([]) :
print "variable a is a list"
(至少在我的系统上,在Mac OS X Yosemite上使用anaconda)
另一个简单的方法来确定一个变量是列表还是元组,或者检查变量类型:
def islist(obj):
if ("list" in str(type(obj))):
return True
else:
return False
不是最优雅的,但我做到了(对于Python 3):
if hasattr(instance, '__iter__') and not isinstance(instance, (str, bytes)):
...
这允许其他可迭代对象(如Django queryset),但不包括字符串和字节串。我通常在接受单个对象ID或对象ID列表的函数中使用这种方法。有时候对象id可以是字符串我不想一个字符一个字符地遍历这些。:)
如果你需要,请使用isinstance。这有点邪恶,因为它排除了自定义序列、迭代器和其他您可能实际需要的东西。然而,有时如果有人传递一个字符串,则需要采取不同的行为。我的偏好是显式检查str或unicode,就像这样:
import types
isinstance(var, types.StringTypes)
注意:不要搞错类型。StringType用于types.StringTypes。后者包含str和unicode对象。
types模块被很多人认为是过时的,更倾向于直接检查对象的类型,所以如果你不想使用上面的方法,你可以选择显式检查str和unicode,就像这样:
isinstance(var, (str, unicode)):
编辑:
更好的是:
isinstance(var, basestring)
最后编辑
在完成这两种操作后,您可以退回到获取正常序列的行为,让非序列引发适当的异常。
See the thing that's "evil" about type checking is not that you might want to behave differently for a certain type of object, it's that you artificially restrict your function from doing the right thing with unexpected object types that would otherwise do the right thing. If you have a final fallback that is not type-checked, you remove this restriction. It should be noted that too much type checking is a code smell that indicates that you might want to do some refactoring, but that doesn't necessarily mean you should avoid it from the getgo.