这是我通常做些什么才能确定输入是list/tuple-但不是str因为很多时候我偶然发现 bug 位置函数传递一个str对象,错误地及目标函数for x in lst假定该lst实际上一个listtuple.

assert isinstance(lst, (list, tuple))

我的问题是︰ 是否有更好的方法达到上述目的?

2009-12-02 18:53:07
问题评论:

type(lst) 是列表?

回答:

我认为

assert not isinstance(lst, basestring)

实际要操作,否则您将错过出提供的大量内容,犹如列表,但不是listtuple的子类.

这是,正确的答案。在 Python 3, basestring已不存在,并仅检查isinstance(lst, str).

有很多的东西可以循环类似列表,如set、 生成器表达式,迭代器。有异国像mmap、 少异国类似array的作用基本上喜欢列表,而且可能很多个我忘记了。

值得注意的,这并不能保证该lst是 iterable,而没有原始 (如 int 会通过此检查)

@PeterGibson 的两个组合将提供有效的、 更严格的检查并确保 iterable 1) lst,2) lst 不是字符串。assert isinstance(lst, (list, tuple)) and assert not isinstance(lst, basestring)

嗯,此解决方案仅检查字符串派生的类型,但内容关于整数、 双精度或任何其它非 iterable 类型?

请记住,在 Python 中我们想要使用"键入回避"。因此,就像一个列表的任何可以被视为列表。因此,没有如果它像一个列表检查类型的列表,只需请参阅。

字符串太,犹如一个列表,但往往就是我们不想。有的时间时就更是问题 !因此,明确检查一个字符串,但然后使用鸭子类型化。

这是我编写有趣的函数。它是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()检查那里做吗?这是什么样的黑客攻击。但它非常重要。

此函数本身以递归方式调用的任何列表之类的。如果我们不精心处理字符串,然后将被看作是一个列表,并一次分裂的一个字符。但然后递归调用者尝试的每个字符视为列表--和它的工作 !甚至一个单字符字符串用作列表 !该函数将保留在本身递归调用直到堆栈溢出。

因为您不能打破级别以下的单字符字符串的字符串,即使一个单字符字符串可以用作列表取决于分解工作每次递归调用进行,类似这样的功能必须字符串,特殊情况。

注︰try/except是最彻底的方法来表达我们的意图。但是,如果由于某种原因此代码是时间关键,我们可能想要将其替换为某种形式的测试,以确定arg是否序列。而不是测试类型,我们可能应该测试行为。如果它有一个.strip()方法,它是一个字符串,所以不考虑它的序列;否则,如果是可索引还是 iterable,它是序列︰

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__()检查,但我注意到在collections模块文档中,有趣的方法是__getitem__();这是有意义,即索引对象的方式。这种方法似乎比__getslice__()更基本使上述更改。

我真的认为这应该是正确的答案。

@stantonk,感谢您说,但我认为,没有已接受的答案时我写了这并不真的希望接受的答案,要更改。

@steveha: srepr是一个非常有趣的想法。但我比您是否需要对特殊情况str的不同意见。str是,到目前为止最明显和常用 iterable srepr中会导致无限递归。但我可以很容易地想象行为方式相同 (有或没有正当理由) 的用户定义的 iterables。而不是str的特殊情况,我们应该承认这种方法可能会遇到无穷递归,并同意它处理的某些方面。我将在应答中发布我的建议。

我认为这绝对是正确的路径。但是,若要处理的特殊情况下 (在该方案中的字符串),我认为我们最好问问题"如何将人告诉差吗?"例如,请考虑函数的参数,可以是电子邮件地址或 (记住一个字符串只是字符的列表) 的单个电子邮件地址的列表。此变量赋予人。怎么能告诉它它是吗?我可以想到的最简单方法是以查看每个列表项中多少个字符。如果大于 1,参数当然也不能为的字符列表。

我已经考虑过这一点,并讨论它与几个其他的人,和我认为srepr()是精确的了。我们需要一个递归函数来处理诸如列表嵌套在另一个列表;但字符串我们会而不是使其打印为"foo"比为<'f', 'o', 'o'>因此一个字符串显式检查好这里意义。同时,真的没有位置始终循环返回 iterable 数据类型和递归的任何其他示例将始终会导致堆栈溢出,所以不需要特殊的属性,此 ("适用范围节拍纯度") 进行测试。

H = "Hello"

if type(H) is list or type(H) is tuple:
    ## Do Something.
else
    ## Do Something.

该 downvoted 的原因?

@tr33hous-可能因为它不会添加任何其他回答没有已。

如果它的工作是彻底的所有这些

不同之处在于它不使用鸭子类型化与其他的 Python 用法者所指出的 (尽管它 does 回答的问题,直接和彻底)。

此答案比其他人因为它没有考虑到鸭子类型化和失败的子类创建简单的情况还不太可接受 (一个典型的例子是 namedtuple 类)。

Python 具有 PHP 风格︰

def is_array(var):
    return isinstance(var, (list, tuple))

Python 是鸭子类型的语言,所以确实应该仔细 var 是否具有属性__getitem__此外名称令人误解,因为还没有阵列模块。和 var 也可能是 numpy.ndarray 或任何其他类型,该类型具有__getitem__请参阅stackoverflow.com/a/1835259/470560查找正确的答案。

@peterhil str也有__getitem__您的支票并不排除因此str

一般来说,循环访问对象的函数适用于字符串,以及元组和列表的事实是更多的功能比 bug。当然也可以使用isinstance或鸭子类型化检查参数,但您为什么应?

这听起来反问,但其实不是。"为什么应该检查参数的类型?"的答案可能要解决实际问题中,没有发现的问题提出建议。为什么是 bug 时字符串传递给该函数?另外︰ 如果字符串传递给此函数时,它是一个 bug,它也是 bug 如果一些其他非列表/元 iterable 传递给它?为什么或为什么不?

我认为问题的常见答案是,可能需要开发人员编写f("abc")期望如同他们写了f(["abc"])函数。或许有一些情况下有意义更多以防止开发人员本身比支持的循环在一个字符串中的字符之间的用例。但我觉得应该是硬和长有关它第一次。

"但我觉得应该是硬和长有关它第一次"。我不会。如果函数为1417列表-y 的函数,然后是,它应该对它们一视同仁 (即给定列表,得到其出背道而驰,事情像这样)。但是,如果它是的函数的一个参数可以是一个字符串的列表 (这是非常普遍的需要),然后强制开发人员使用该函数总是输入它们的参数数组内看起来有点多。此外,考虑将如何处理,比如 JSON 输入。您确实想将不同的字符串对象的列表。

请输入您的翻译

Python: check if an object is a list or tuple (but not string)

确认取消