在 Python 中,众所周知,在检查迭代器(列表、字典等)中的成员资格并在字符串中查找子字符串。我的问题是关于如何实现in以实现以下所有目标:1) 测试成员资格,2) 测试子字符串和 3) 访问 for 循环中的下一个元素。 例如,当执行for i in myList:
或if i in myList:
时,是否调用myList.__next__()
?如果它确实调用了它,那么它如何处理字符串,因为str对象不是迭代器(如 Python 2.7 中检查的那样),因此没有next()方法?如果无法详细讨论in的实现,如果在此处提供它的要点,将不胜感激。
类可以通过定义__contains__
方法来定义in
运算符在该类的实例上的工作方式。
Python 数据模型文档说:
对于没有定义
__contains__()
的对象,成员资格测试首先通过__iter__()
尝试迭代,然后通过__getitem__()
尝试旧的序列迭代协议,请参阅语言参考中的这一部分。
Python 语言参考的第 6.10.2 节 "成员资格测试操作"是这样说的:
操作员
in
并not in
成员资格测试。x in s
计算结果为True
x是否是s的成员,否则False
。x not in s
返回x in s
的否定。所有内置序列和集合类型都支持此功能以及字典,in
字典测试字典是否具有给定键。对于容器类型(如列表、元组、集合、冻结集、字典或集合.deque),表达式x in y
等效于any(x is e or x == e for e in y)
。对于字符串和字节类型,当且仅当x是y的子字符串时,
x in y
True
。等效测试是y.find(x) != -1
。空字符串始终被视为任何其他字符串的子字符串,因此"" in "abc"
将返回True
。对于定义
__contains__()
方法的用户定义类,如果返回 truey.__contains__(x)
值,则x in y
返回True
,否则False
返回。对于不定义
__contains__()
但定义__iter__()
的用户定义类,如果在迭代y
时产生一些与x == z
z
的值,则x in y
True
。如果在迭代期间引发异常,就好像in
引发该异常一样。最后,尝试旧式迭代协议:如果一个类定义了
__getitem__()
,则当且仅当存在非负整数索引i使得x == y[i]
并且所有较低的整数索引不会引发IndexError
异常时,x in y
True
。(如果引发任何其他异常,就好像in
引发了该异常)。运算符
not in
定义为具有in
的反真值。
如上文注释所示,表达式运算符in
不同于构成for
语句一部分的关键字in
。在 Python 语法中,in
被"硬编码"为for
语法的一部分:
for_stmt ::= "for" target_list "in" expression_list ":" suite ["else" ":" suite]
因此,在for
语句的上下文中,in
的行为不是运算符,它只是将target_list
与expression_list
分开的语法标记。
Python 有__contains__
特殊方法,当你执行item in collection
时会使用。
例如,下面是一个"__contains__"所有偶数的类:
>>> class EvenNumbers:
... def __contains__(self, item):
... return item % 2 == 0
...
>>> en = EvenNumbers()
>>> 2 in en
True
>>> 3 in en
False
>>>