这是我通常所做的,以确定输入是一个列表/元组-而不是一个str。因为很多次我偶然发现错误,其中一个函数错误地传递了一个str对象,而目标函数在lst中执行x,假设lst实际上是一个列表或元组。
assert isinstance(lst, (list, tuple))
我的问题是:有没有更好的方法来实现这个目标?
这是我通常所做的,以确定输入是一个列表/元组-而不是一个str。因为很多次我偶然发现错误,其中一个函数错误地传递了一个str对象,而目标函数在lst中执行x,假设lst实际上是一个列表或元组。
assert isinstance(lst, (list, tuple))
我的问题是:有没有更好的方法来实现这个目标?
当前回答
记住,在Python中,我们希望使用“duck typing”。所以,任何类似于列表的东西都可以被视为列表。所以,不要检查列表的类型,只要看看它是否像一个列表。
但是字符串也像一个列表,这通常不是我们想要的。有时候这甚至是个问题!因此,显式检查字符串,然后使用duck typing。
这是我写的一个函数,只是为了好玩。它是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()检查在那里做什么呢?这是一种hack。但这是必要的。
这个函数在任何类似于列表的东西上递归地调用自己。如果我们不专门处理字符串,那么它将被视为一个列表,并一次分割一个字符。但随后递归调用将尝试将每个字符视为列表—这将工作!即使只有一个字符的字符串也可以作为列表!函数将继续递归地调用自己,直到堆栈溢出。
像这样的函数,依赖于每个递归调用分解要完成的工作,必须使用特殊情况的字符串——因为您不能分解一个字符串级别以下的字符串,甚至一个字符串也像一个列表。
注意: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__(),但我注意到在集合模块文档中,有趣的方法是__getitem__();这很有意义,这就是索引对象的方法。这似乎比__getslice__()更基本,所以我改变了上面的内容。
其他回答
我倾向于这样做(如果我真的,真的必须这么做的话):
for i in some_var:
if type(i) == type(list()):
#do something with a list
elif type(i) == type(tuple()):
#do something with a tuple
elif type(i) == type(str()):
#here's your string
我在tensorflow中找到了这样一个名为is_sequence的函数。
def is_sequence(seq):
"""Returns a true if its input is a collections.Sequence (except strings).
Args:
seq: an input sequence.
Returns:
True if the sequence is a not a string and is a collections.Sequence.
"""
return (isinstance(seq, collections.Sequence)
and not isinstance(seq, six.string_types))
我已经核实了,它符合你的需求。
记住,在Python中,我们希望使用“duck typing”。所以,任何类似于列表的东西都可以被视为列表。所以,不要检查列表的类型,只要看看它是否像一个列表。
但是字符串也像一个列表,这通常不是我们想要的。有时候这甚至是个问题!因此,显式检查字符串,然后使用duck typing。
这是我写的一个函数,只是为了好玩。它是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()检查在那里做什么呢?这是一种hack。但这是必要的。
这个函数在任何类似于列表的东西上递归地调用自己。如果我们不专门处理字符串,那么它将被视为一个列表,并一次分割一个字符。但随后递归调用将尝试将每个字符视为列表—这将工作!即使只有一个字符的字符串也可以作为列表!函数将继续递归地调用自己,直到堆栈溢出。
像这样的函数,依赖于每个递归调用分解要完成的工作,必须使用特殊情况的字符串——因为您不能分解一个字符串级别以下的字符串,甚至一个字符串也像一个列表。
注意: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__(),但我注意到在集合模块文档中,有趣的方法是__getitem__();这很有意义,这就是索引对象的方法。这似乎比__getslice__()更基本,所以我改变了上面的内容。
为了提高可读性和最佳实践,请尝试以下方法:
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
希望能有所帮助。
就这么做
if type(lst) in (list, tuple):
# Do stuff