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

In Python, how is the in operator implemented to work? Does it use the next() method of the iterators?

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

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

时使用

例如,这里有一个 class,其中“__contains__”都是偶数:

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

class 可以通过定义 __contains__ 方法来定义 in 运算符如何作用于 class 的实例。

Python data model documentation 说:

For objects that don’t define __contains__(), the membership test first tries iteration via __iter__(), then the old sequence iteration protocol via __getitem__(), see this section in the language reference.

Section 6.10.2, "Membership test operations", of the Python language reference 有话要说:

The operators in and not in test for membership. x in s evaluates to True if x is a member of s, and False otherwise. x not in s returns the negation of x in s. All built-in sequences and set types support this as well as dictionary, for which in tests whether the dictionary has a given key. For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression x in y is equivalent to any(x is e or x == e for e in y).

For the string and bytes types, x in y is True if and only if x is a substring of y. An equivalent test is y.find(x) != -1. Empty strings are always considered to be a substring of any other string, so "" in "abc" will return True.

For user-defined classes which define the __contains__() method, x in y returns True if y.__contains__(x) returns a true value, and False otherwise.

For user-defined classes which do not define __contains__() but do define __iter__(), x in y is True if some value z with x == z is produced while iterating over y. If an exception is raised during the iteration, it is as if in raised that exception.

Lastly, the old-style iteration protocol is tried: if a class defines __getitem__(), x in y is True if and only if there is a non-negative integer index i such that x == y[i], and all lower integer indices do not raise IndexError exception. (If any other exception is raised, it is as if in raised that exception).

The operator not in is defined to have the inverse true value of in.

正如上面的注释所示,表达式运算符 in 关键字 in 不同构成 the for statement 的一部分。在Python语法中,in是"hardcoded"作为for语法的一部分:

for_stmt ::=  "for" target_list "in" expression_list ":" suite
              ["else" ":" suite]

所以在 for 语句的上下文中,in 不作为运算符,它只是一个语法标记,用于将 target_list 与 [=60= 分开].