为什么要in为生成器定义运算符?
>>> def foo():
... yield 42
...
>>>
>>> f = foo()
>>> 10 in f
False
Run Code Online (Sandbox Code Playgroud)
可能的用例有哪些?
我知道range(...)对象__contains__定义了一个函数,这样我们就可以做这样的事情:
>>> r = range(10)
>>> 4 in r
True
>>> r.__contains__
<method-wrapper '__contains__' of range object at 0x7f82bd51cc00>
Run Code Online (Sandbox Code Playgroud)
但f上面没有__contains__方法。
“可能的用例是什么?” 检查生成器是否会产生一些值。
Dunder 方法充当与其关联的特定语法的挂钩。__contains__不是某种到 的一对一映射x in y。该语言最终定义了这些运算符的语义。
从成员资格测试的文档中,我们看到有多种x in y评估方法,具体取决于所涉及对象的各种属性。我已经强调了生成器对象的相关内容,这些对象没有定义 a__contains__ 但可以迭代,即它们定义了一个__iter__方法:
正在或未参加会员资格测试的运营商。
x in s计算结果为Truex 是否为 s 的成员,否则为 False。x not in s返回 的否定x in s。所有内置序列和集合类型都支持此功能以及字典,其中测试字典是否具有给定的键。对于列表、元组、集合、frozenset、dict 或 collections.deque 等容器类型,y 中的表达式 x 等效于any(x is e or x == e for e in y)。对于 string 和 bytes 类型,
x in yisTrue当且仅当x是 的子字符串y。等效测试是y.find(x) != -1. 空字符串始终被视为任何其他字符串的子字符串,因此"" in "abc"将返回 True。对于定义该
__contains__()方法的用户定义类,True如果y.__contains__(x)返回真值,则返回 x in y,False否则返回。对于未定义contains () 但定义了定义的用户定义类
__iter__(),x in y如果在迭代 时生成 表达式为true 的True某个值。如果在迭代期间引发异常,就好像引发了该异常。zx is z or x == zy最后,尝试旧式迭代协议:如果一个类定义
__getitem__(),x in y是True当且仅当存在一个非负整数索引使得i,x is y[i] or x == y[i]并且没有更低的整数索引引发 IndexError 异常。(如果引发任何其他异常,则就像引发该异常一样)。该运算符
not in被定义为具有 in 的逆真值。
总而言之,x in y将为以下对象定义:
__contains____iter____getitem__)发电机分为 3 种。
更广泛的一点是,您确实不应该直接使用 dunder 方法,除非您真正了解它们在做什么。即便如此,最好还是避免这种情况。
通常不值得尝试通过使用某些东西来达到可信或简洁的效果:
x.__lt__(y)
Run Code Online (Sandbox Code Playgroud)
代替:
x < y
Run Code Online (Sandbox Code Playgroud)
您至少应该明白,这可能会发生:
>>> (1).__lt__(3.)
NotImplemented
>>>
Run Code Online (Sandbox Code Playgroud)
如果您只是天真地做这样的事情,filter((1).__lt__, iterable) 那么您可能遇到了错误。
| 归档时间: |
|
| 查看次数: |
457 次 |
| 最近记录: |