我正在研究包含数千个出现的代码库foo in list(bar)
,例如:
- 作为布尔表达式:
if foo in list(bar) or ...:
...
- 在 for 循环中:
for foo in list(bar):
...
- 在生成器表达式中:
",".join(str(foo) for foo in list(bar))
是否存在这样的场景(例如给定版本的 Python、类型检查器的已知行为等...),其中foo in list(bar)
不仅仅是内存昂贵的版本foo in bar
?我在这里遗漏了什么?
我有时会做/看到
bar
在循环中被修改的情况,例如:有您的替代者,情况就提高了
RuntimeError: Set changed size during iteration
。在线尝试!
Python标准库中的一个例子
还有几十个(很多是出于上述原因,但不是全部)。
这里有所不同:
这会打印一个空行。使用替换
a r
后,它会打印。在线尝试!
如果
foo
和bar
都是字符串,成员测试的行为会有所不同。<str> in <str>
检查子字符串,而<str> in list(<str>)
检查字符。关于循环,不要让语法欺骗你,它与布尔表达式不同。循环使用可迭代协议(例如
__iter__
),而布尔表达式使用成员资格测试协议(例如__contains__
,或者它会回退到可迭代协议)因此,任何人都可以创建一个以这种方式工作的类型:
大多数内置类型都“表现良好”。然而,一个重要的例外可能是
str
和其他类似类型(bytes
,bytearray
):此外,至少对于一个流行的图书馆来说,
numpy
情况并非如此:什么时候
bar
是生成器,bar
并且list(bar)
可能存在其他差异。以下是一个例子:在第一种情况下,
if foo in abc()
不会耗尽生成器。由于惰性求值,一旦'a'
产生,生成器将不会再产生任何项。在第二种情况下,
if foo in list(abc())
耗尽生成器,从而引发异常。因此'with list()'
永远不会被打印。