这是我通常所做的,以确定输入是一个列表/元组-而不是一个str。因为很多次我偶然发现错误,其中一个函数错误地传递了一个str对象,而目标函数在lst中执行x,假设lst实际上是一个列表或元组。

assert isinstance(lst, (list, tuple))

我的问题是:有没有更好的方法来实现这个目标?


当前回答

仅在python2中(不是python3):

assert not isinstance(lst, basestring)

实际上是你想要的,否则你会错过很多像列表一样的东西,但不是list或tuple的子类。

其他回答

这不是为了直接回答OP,但我想分享一些相关的想法。

我对上面@steveha的回答非常感兴趣,它似乎给出了一个鸭子打字似乎崩溃的例子。然而,仔细一想,他的例子表明duck类型很难符合,但这并不意味着str值得任何特殊处理。

毕竟,非str类型(例如,维护一些复杂递归结构的用户定义类型)可能会导致@steveha srepr函数导致无限递归。虽然承认这不大可能,但我们不能忽视这种可能性。因此,我们不应该在srepr中使用特殊的str大小写,而是应该阐明当产生无限递归时,我们希望srepr做什么。

一种合理的方法似乎是简单地打破矩列表(arg) == [arg]中srepr的递归。事实上,这将完全解决str的问题,而不需要任何isinstance。

然而,一个非常复杂的递归结构可能会导致一个无限循环,其中list(arg) == [arg]永远不会发生。因此,虽然上面的检查很有用,但还不够。我们需要对递归深度有一个硬性限制。

我的观点是,如果你打算处理任意的参数类型,通过duck类型处理str要比处理你可能(理论上)遇到的更一般的类型容易得多。因此,如果您觉得需要排除str实例,您应该要求参数是您显式指定的少数类型之一的实例。

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)

仅在python2中(不是python3):

assert not isinstance(lst, basestring)

实际上是你想要的,否则你会错过很多像列表一样的东西,但不是list或tuple的子类。

就这么做

if type(lst) in (list, tuple):
    # Do stuff

以“鸭子打字”的方式,怎么样

try:
    lst = lst + []
except TypeError:
    #it's not a list

or

try:
    lst = lst + ()
except TypeError:
    #it's not a tuple

分别。这避免了isinstance / hasattr自省的事情。

你也可以反过来检查:

try:
    lst = lst + ''
except TypeError:
    #it's not (base)string

所有变量实际上并不改变变量的内容,而是意味着重新赋值。我不确定在某些情况下这是否不可取。

有趣的是,如果lst是一个列表(不是元组),使用“in place”赋值+=在任何情况下都不会引发TypeError。这就是为什么作业是这样做的。也许有人能解释一下原因。