为什么' in'关键字声明它需要一个可迭代的对象?

时间:2015-10-25 04:22:24

标签: python

>>> 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__的对象?

3 个答案:

答案 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

the documentation -

中对此进行了解释
  

对于定义__contains__()方法的用户定义类,x in y当且仅当y.__contains__(x)为真时才为真。

     

对于未定义__contains__()但定义__iter__()的用户定义的类,如果生成x in y的某些值z,则x == z为真迭代y。如果在迭代期间引发异常,那就好像是在异常中引发异常。

答案 1 :(得分:3)

  

是否有in个关键字声称想要一个可迭代对象,而它真正想要的是一个实现__contains__的对象?

x in thingfor 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