在 Python 中,in 操作符是如何实现的?它是否使用迭代器的 next() 方法?

bp1*_*p14 11 python in-operator

在 Python 中,众所周知,检查迭代器(列表、字典等)中的成员资格并在字符串中查找子字符串。我的问题是关于如何实现in以实现以下所有内容:1) 测试成员资格,2) 测试子字符串和 3) 访问 for 循环中的下一个元素。例如,当for i in myList:if i in myList:被执行时,in callmyList.__next__()吗?如果它确实调用了它,那么它如何处理字符串,因为str对象不是迭代器(如在 Python 2.7 中检查的那样),因此没有next()方法?如果无法详细讨论in的实现,请在此处提供其要点。

Dan*_*den 13

一个类可以in通过定义一个__contains__方法来定义操作符如何处理该类的实例。

Python数据模型文档说:

对于没有定义的对象,__contains__()成员资格测试首先尝试迭代 via __iter__(),然后是旧的序列迭代协议 via __getitem__(),请参阅语言参考中的这一部分

Python 语言参考的第 6.10.2 节“成员资格测试操作”是这样说的:

运营商innot in会员资格测试。x in s计算结果为True,如果X是一个成员小号,和False其它。x not in s返回 的否定x in s。所有内置的序列和集合类型都支持这个以及字典,用于in测试字典是否具有给定的键。对于 list、tuple、set、frozenset、dict 或 collections.deque 等容器类型,表达式x in y等效于any(x is e or x == e for e in y)

对于 string 和 bytes 类型,x in yisTrue当且仅当xy的子字符串。一个等效的测试是y.find(x) != -1。空字符串始终被视为任何其他字符串的子字符串,因此"" in "abc"将返回True.

为它定义了用户定义的类__contains__()的方法,x in y将返回True如果y.__contains__(x)返回一个真值,和False以其他方式。

对于不定义用户定义的类__contains__(),但不限定__iter__()x in yTrue,如果某个值zx == z同时迭代产生y。如果在迭代期间in引发异常,就好像引发了该异常。

最后,尝试旧式迭代协议:如果一个类定义了__getitem__()x in y则是True当且仅当存在非负整数索引i使得x == y[i],并且所有较低的整数索引都不会引发IndexError异常。(如果引发任何其他异常,就好像in引发了该异常)。

运算符not in被定义为具有 的反真值in

作为注释上面所表示的,表达式算子 in是从不同的关键字 in形成的一部分for语句。在 Python 语法中,in被“硬编码”为以下语法的一部分for

for_stmt ::=  "for" target_list "in" expression_list ":" suite
              ["else" ":" suite]
Run Code Online (Sandbox Code Playgroud)

因此,在for语句的上下文中,in它不充当运算符,它只是一个target_listexpression_list.


iBu*_*Bug 5

Python 有__contains__特殊的方法,当您执行item in collection.

例如,这是一个“__包含__”所有偶数的类:

>>> class EvenNumbers:
...   def __contains__(self, item):
...     return item % 2 == 0
...
>>> en = EvenNumbers()
>>> 2 in en
True
>>> 3 in en
False
>>>
Run Code Online (Sandbox Code Playgroud)