Ami*_*ory 4 python language-lawyer
考虑以下两个类:
class Foo0(object):
pass
class Foo1(object):
def __contains__(self, _):
return False
Run Code Online (Sandbox Code Playgroud)
它们都不是可迭代的,可以通过尝试来观察for i in Foo1(): pass:
Traceback (most recent call last):
File "stuff.py", line 11, in <module>
for i in Foo1(): pass
TypeError: 'Foo1' object is not iterable
Run Code Online (Sandbox Code Playgroud)
相反的,3 in Foo1()是有效的(因为Foo1有__contains__),而3 in Foo0()不是:
Traceback (most recent call last):
File "stuff.py", line 9, in <module>
3 in Foo0()
TypeError: argument of type 'Foo0' is not iterable
Run Code Online (Sandbox Code Playgroud)
我发现错误有误导性.重点不是Foo0不可迭代 - 毕竟Foo1不可迭代,所以这不是固有的原因.此外,正如@niemmi和@tobias_k在下面正确说明的那样,如果一个类不支持__contains__,__iter__则用作回退,这是导致此错误的直接原因.然而,这会使事情变得更糟,因为用户可能会尝试通过实现来解决此错误__iter__,这是一种非常低效的实现方法__contains__.
那为什么选择这个错误呢?
如果对象没有__contains__方法,Python会自动尝试迭代它以查看它是否可以找到该元素.由于Foo0不是可迭代的,您将看到错误.
更新:Python语言参考更详细地解释了这一点:
对于定义contains()方法的用户定义类,当y且仅当y时,y中的x为true.contains(x)是真的.
对于未定义contains()但定义iter()的用户定义类,如果在迭代y时生成某些具有x == z的值z,则y中的x为true.如果在迭代期间引发异常,则就好像在异常中引发异常一样.
最后,尝试了旧式迭代协议:如果一个类定义了getitem(),则y中的x为真,当且仅当存在非负整数索引i时,x == y [i],并且全部更低整数索引不会引发IndexError异常.(如果引发任何其他异常,就好像在异常中引发异常).
| 归档时间: |
|
| 查看次数: |
1175 次 |
| 最近记录: |