【问题标题】:Why does the 'in' keyword claim it needs an iterable object?为什么'in'关键字声称它需要一个可迭代对象?
【发布时间】:2015-10-25 04:22:24
【问题描述】:
>>> 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__ 的对象时,是否有理由声称需要一个可迭代对象?

【问题讨论】:

    标签: python


    【解决方案1】:

    它声称需要一个可迭代对象,因为如果对象的类没有实现 __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__() 方法的用户定义类,当且仅当y.__contains__(x) 为真时,x in y 为真。

    对于未定义 __contains__() 但定义 __iter__() 的用户定义类,如果在迭代 y 时产生了 zx == z 的某个值,则 x in y 为真。如果在迭代过程中引发了异常,就如同引发了该异常。

    【讨论】:

    • 有道理。那我猜这个错误信息有点不准确。
    • 不一定。如果您首先尝试包含,失败并且接下来要退回到迭代,那么迭代位就是异常会冒泡的地方。所以消息与不可恢复的错误点是一致的。
    • 是的,文档中也提到了这一点 - 如果在迭代期间引发异常,就好像引发了该异常。 .
    【解决方案2】:

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

    x in thingfor x in thing 密切相关。几乎所有支持x in thing 的东西都遵循x in thing 为真的规则,当且仅当thing 上的for 循环将找到等于x 的元素。特别是,如果对象支持迭代但不支持__contains__,Python 将使用迭代作为in 测试的后备。

    错误消息可能会说它需要__contains__,但这与当前消息一样错误,因为__contains__ 并不是绝对必要的。它可以说它需要一个容器,但目前还不清楚什么是容器。例如,dicts 支持in,但称它们为容器是有问题的。当前消息说它需要一个可迭代的,与其他选项一样准确。它的优点是在实践中,“是否可迭代”比“是否为容器”或“是否支持__contains__”更能确定实际对象是否支持in

    【讨论】:

    • 它们是相关的,是的,但仍然是两个不同的东西。 for x in also_non_iterable() 仍会引发 TypeError。所以这是一个单独的错误。用object is not iterable or a container 代替原来的错误似乎很容易。
    【解决方案3】:

    in 有两种不同的用法:

    • 测试容器是否有值(例如,左参数实现__contains__
    • 遍历一个序列(例如,正确的参数是Iterable

    【讨论】:

    • 好点。但是从一个具有 _contain_ 的对象(比如字典)中迭代一个大列表(这里是松散的用法)是非常低效的。或者更是如此。那么对于成员资格的测试不会与序列遍历和特权包含检查不同吗?
    猜你喜欢
    • 2014-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多