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

assert isinstance(lst, (list, tuple))

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


当前回答

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

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

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

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

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

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

其他回答

仅在python2中(不是python3):

assert not isinstance(lst, basestring)

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

str对象没有__iter__属性

>>> hasattr('', '__iter__')
False 

你可以检查一下

assert hasattr(x, '__iter__')

这也会对任何其他不可迭代对象抛出一个漂亮的AssertionError。

编辑: 正如Tim在评论中提到的,这只适用于python2。X,不是3。X

assert (type(lst) == list) | (type(lst) == tuple), "Not a valid lst type, cannot be string"

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."

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)