Python 是“…”;。。。“对象不可编辑”;“的误导性错误”;x在y中;?
考虑以下两类:Python 是“…”;。。。“对象不可编辑”;“的误导性错误”;x在y中;?,python,language-lawyer,Python,Language Lawyer,考虑以下两类: class Foo0(object): pass class Foo1(object): def __contains__(self, _): return False 这两种方法都不可移植,可以通过在Foo1()中为i尝试:pass: Traceback (most recent call last): File "stuff.py", l
class Foo0(object):
pass
class Foo1(object):
def __contains__(self, _):
return False
这两种方法都不可移植,可以通过在Foo1()中为i尝试:pass
:
Traceback (most recent call last):
File "stuff.py", line 11, in <module>
for i in Foo1(): pass
TypeError: 'Foo1' object is not iterable
我发现这个错误有误导性。问题的关键不是
Foo0
不可编辑-毕竟Foo1
也不可编辑,所以这不是内在原因。此外,正如@niemmi和@tobias_k在下面正确指出的那样,如果一个类不支持\uuuuu包含
,\uuuuu iter\uuuu
将用作回退,这是导致此错误的直接原因。然而,这会让事情变得更糟,因为用户可能会试图通过实现\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
来解决此错误,这是一种非常低
那么,为什么选择这个作为错误呢?如果对象没有方法,Python会自动尝试对其进行迭代,以查看是否可以找到元素。因为
Foo0
不是一个iterable,所以您将看到错误
更新:更详细地解释这一点:
对于定义contains()方法的用户定义类,y中的x为真当且仅当y.contains(x)为真时
对于不定义包含()但定义iter()的用户定义类,如果在y上迭代时生成某个值z且x==z,则y中的x为真。如果在迭代过程中引发异常,就好像在中引发了该异常一样
最后,尝试旧式的迭代协议:如果一个类定义了getitem(),当且仅当存在一个非负整数索引i,使得x==y[i],并且所有较低的整数索引都不会引发索引器异常时,y中的x为真。(如果引发任何其他异常,则与引发该异常一样)
谢谢,尼米,这也是我的理解。然而,它解释了这是如何发生的,而不是如果这是语言设计者想要的理由。回答得不错。错误消息应该可以解释根本原因,而不是回退失败的原因。
Traceback (most recent call last):
File "stuff.py", line 9, in <module>
3 in Foo0()
TypeError: argument of type 'Foo0' is not iterable