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