在 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= 分开].
在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
andnot in
test for membership.x in s
evaluates toTrue
if x is a member of s, andFalse
otherwise.x not in s
returns the negation ofx in s
. All built-in sequences and set types support this as well as dictionary, for whichin
tests whether the dictionary has a given key. For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expressionx in y
is equivalent toany(x is e or x == e for e in y)
.For the string and bytes types,
x in y
isTrue
if and only if x is a substring of y. An equivalent test isy.find(x) != -1
. Empty strings are always considered to be a substring of any other string, so"" in "abc"
will returnTrue
.For user-defined classes which define the
__contains__()
method,x in y
returnsTrue
ify.__contains__(x)
returns a true value, andFalse
otherwise.For user-defined classes which do not define
__contains__()
but do define__iter__()
,x in y
isTrue
if some valuez
withx == z
is produced while iterating overy
. If an exception is raised during the iteration, it is as ifin
raised that exception.Lastly, the old-style iteration protocol is tried: if a class defines
__getitem__()
,x in y
isTrue
if and only if there is a non-negative integer index i such thatx == y[i]
, and all lower integer indices do not raiseIndexError
exception. (If any other exception is raised, it is as ifin
raised that exception).The operator
not in
is defined to have the inverse true value ofin
.
正如上面的注释所示,表达式运算符 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= 分开].