这是我通常所做的,以确定输入是一个列表/元组-而不是一个str。因为很多次我偶然发现错误,其中一个函数错误地传递了一个str对象,而目标函数在lst中执行x,假设lst实际上是一个列表或元组。
assert isinstance(lst, (list, tuple))
我的问题是:有没有更好的方法来实现这个目标?
这是我通常所做的,以确定输入是一个列表/元组-而不是一个str。因为很多次我偶然发现错误,其中一个函数错误地传递了一个str对象,而目标函数在lst中执行x,假设lst实际上是一个列表或元组。
assert isinstance(lst, (list, tuple))
我的问题是:有没有更好的方法来实现这个目标?
当前回答
Python 3有这个:
from typing import List
def isit(value):
return isinstance(value, List)
isit([1, 2, 3]) # True
isit("test") # False
isit({"Hello": "Mars"}) # False
isit((1, 2)) # False
因此,要检查list和tuple,它将是:
from typing import List, Tuple
def isit(value):
return isinstance(value, List) or isinstance(value, Tuple)
其他回答
我倾向于这样做(如果我真的,真的必须这么做的话):
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
duck-typing的另一个版本,用于帮助区分类似字符串的对象和其他类似序列的对象。
类字符串对象的字符串表示就是字符串本身,所以你可以检查你是否从str构造函数返回了一个相等的对象:
# If a string was passed, convert it to a single-element sequence
if var == str(var):
my_list = [var]
# All other iterables
else:
my_list = list(var)
这应该适用于所有与str兼容的对象和所有类型的可迭代对象。
H = "Hello"
if type(H) is list or type(H) is tuple:
## Do Something.
else
## Do Something.
记住,在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 3:
import collections.abc
if isinstance(obj, collections.abc.Sequence) and not isinstance(obj, str):
print("`obj` is a sequence (list, tuple, etc) but not a string or a dictionary.")
在3.3版更改:将“集合抽象基类”的全局命名空间从abc移动到集合。美国广播公司(abc)模块。为了向后兼容,它们将继续在这个模块中可见,直到3.8版,它将停止工作。
Python 2:
import collections
if isinstance(obj, collections.Sequence) and not isinstance(obj, basestring):
print "`obj` is a sequence (list, tuple, etc) but not a string or unicode or dictionary."