>>> non_iterable = 1
>>> 5 in non_iterable
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'int' object is not iterable
>>> class also_non_iterable:
... def __contains__(self,thing):
... return True
>>> 5 in also_non_iterable()
True
>>> isinstance(also_non_iterable(), Iterable)
False
是否有in
个关键字声称想要一个可迭代对象,而它真正想要的是一个实现__contains__
的对象?
答案 0 :(得分:13)
它声称想要一个可迭代的,因为如果对象的类没有实现__contains__
,那么in
会尝试遍历该对象并检查这些值是否等于价值收益率。
显示 -
的示例>>> class C:
... def __iter__(self):
... return iter([1,2,3,4])
>>>
>>> c = C()
>>> 2 in c
True
>>> 5 in c
False
中对此进行了解释
对于定义
__contains__()
方法的用户定义类,x in y
当且仅当y.__contains__(x)
为真时才为真。对于未定义
__contains__()
但定义__iter__()
的用户定义的类,如果生成x in y
的某些值z
,则x == z
为真迭代y
。如果在迭代期间引发异常,那就好像是在异常中引发异常。
答案 1 :(得分:3)
是否有
in
个关键字声称想要一个可迭代对象,而它真正想要的是一个实现__contains__
的对象?
x in thing
和for x in thing
密切相关。支持x in thing
的几乎所有内容都遵循x in thing
为真的规则,当且仅当thing
上的for循环找到等于x
的元素时。特别是,如果一个对象支持迭代但不支持__contains__
,Python将使用迭代作为in
测试的后备。
错误消息可能会说它需要__contains__
,但这与当前消息一样错误,因为__contains__
并非严格必要。可以说它需要一个容器,但它不能立即清楚什么算作容器。例如,dicts支持in
,但称它们为容器是值得怀疑的。当前消息表示它需要可迭代,与其他选项一样准确。它的优点是在实践中,它是可迭代的#34;是一个更好的检查而不是&#34;它是一个容器&#34;或者&#34;是否支持__contains__
&#34;用于确定实际对象是否支持in
。
答案 2 :(得分:1)
in
有两种不同的用途:
__contains__
)Iterable
)