这是我通常所做的,以确定输入是一个列表/元组-而不是一个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."