这是我通常要做的,以确定输入是list
/tuple
,而不是str
。因为很多次我偶然发现了一些bug,其中一个函数错误地传递了一个str
对象,而目标函数假设lst
实际上是一个list
或tuple
,则执行for x in lst
。
assert isinstance(lst, (list, tuple))
我的问题是:有没有更好的方法来实现这一点?
发布于 2009-12-03 02:56:52
仅在python 2中(不是python 3):
assert not isinstance(lst, basestring)
实际上是你想要的,否则你会错过很多像lists一样的东西,但不是list
或tuple
的子类。
发布于 2009-12-03 03:30:14
请记住,在Python中,我们希望使用“鸭子类型”。因此,任何类似于列表的行为都可以被视为列表。因此,不要检查列表的类型,只需查看它是否像列表一样。
但是字符串也像一个列表,这通常不是我们想要的。有时候它甚至是一个问题!所以,显式地检查一个字符串,然后使用duck类型。
这是我写的一个有趣的函数。它是repr()
的一个特殊版本,可以打印尖括号('<','>')中的任何序列。
def srepr(arg):
if isinstance(arg, basestring): # Python 3: isinstance(arg, str)
return repr(arg)
try:
return '<' + ", ".join(srepr(x) for x in arg) + '>'
except TypeError: # catch when for loop fails
return repr(arg) # not a sequence so just return repr
总的来说,这是干净和优雅的。但是isinstance()
检查在那里做什么呢?这是一种黑客行为。但这是必不可少的。
此函数递归地对任何行为类似列表的对象调用自身。如果我们没有特别处理这个字符串,那么它就会被当作一个列表来处理,并且一次拆分一个字符。但是,递归调用将尝试将每个字符视为一个列表--它就可以工作了!即使只有一个字符的字符串也可以作为列表使用!该函数将继续递归地调用自身,直到堆栈溢出。
像这样的函数,依赖于每个递归调用分解要完成的工作,必须处理特殊情况的字符串--因为你不能分解一个低于一个字符的字符串,甚至一个一个字符的字符串也像一个列表。
注意:try
/except
是表达我们意图的最简洁的方式。但是,如果这段代码是时间关键型的,我们可能希望用某种测试来替换它,看看arg
是否是一个序列。我们应该测试行为,而不是测试类型。如果它有一个.strip()
方法,它就是一个字符串,所以不要认为它是一个序列;否则,如果它是可索引或可迭代的,它就是一个序列:
def is_sequence(arg):
return (not hasattr(arg, "strip") and
hasattr(arg, "__getitem__") or
hasattr(arg, "__iter__"))
def srepr(arg):
if is_sequence(arg):
return '<' + ", ".join(srepr(x) for x in arg) + '>'
return repr(arg)
编辑:我最初编写上面的代码时检查了__getslice__()
,但我注意到在collections
模块文档中,有趣的方法是__getitem__()
;这是有意义的,这就是如何索引对象的。这似乎比__getslice__()
更基本,所以我更改了上面的设置。
发布于 2014-02-03 16:48:45
H = "Hello"
if type(H) is list or type(H) is tuple:
## Do Something.
else
## Do Something.
https://stackoverflow.com/questions/1835018
复制相似问题