Kel*_*ndy 15 python list language-lawyer
我偶尔会使用“技巧”来通过自身的映射版本来扩展列表,例如有效地计算 2 的幂:
from operator import mul
powers = [1]
powers += map(mul, [2] * 10, powers)
print(powers) # prints [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
Run Code Online (Sandbox Code Playgroud)
这依赖于+=立即将每个值附加map到列表中,以便map随后找到它并继续该过程。换句话说,它需要像这样工作:
powers = [1]
for value in map(mul, [2] * 10, powers):
powers.append(value)
Run Code Online (Sandbox Code Playgroud)
而不是首先像这样计算和存储整个右侧,最终powers结果是[1, 2]:
powers = [1]
powers += list(map(mul, [2] * 10, powers))
Run Code Online (Sandbox Code Playgroud)
是否在某个地方保证它能像以前那样工作?我检查了可变序列类型s += t文档,但除了暗示和的等价性之外,它没有说太多s.extend(t)。它确实引用了MutableSequence,其源代码包括:
def extend(self, values):
'S.extend(iterable) -- extend sequence by appending elements from the iterable'
if values is self:
values = list(values)
for v in values:
self.append(v)
Run Code Online (Sandbox Code Playgroud)
def __iadd__(self, values):
self.extend(values)
return self
Run Code Online (Sandbox Code Playgroud)
这确实表明它确实应该像我想要的那样工作,但是某些源代码并不像文档中的保证那样安全。
我没有看到任何测试或文档可以保证贪婪行为;但是,我确实认为这是预期的行为,并且野外代码依赖于它。
\nFWIW,+=与列表相当于list.extend(),所以你的“技巧”归结为:
>>> powers = [1]\n>>> powers.extend(2*x for x in islice(powers, 10))\n>>> powers\n[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]\nRun Code Online (Sandbox Code Playgroud)\n虽然我还没有找到+=or的保证extend,但我们确实保证列表迭代器允许在迭代时发生突变。\xc2\xb9 因此,这段代码是有坚实基础的:
>>> powers = [1]\n>>> for x in powers:\n if len(powers) == 10:\n break\n powers.append(2 * x)\n\n>>> powers\n[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]\nRun Code Online (Sandbox Code Playgroud)\n\xc2\xb9 请参阅表后面的第二段:\n https://docs.python.org/3/library/stdtypes.html#common-sequence-operations:
\n\n\n可变序列上的正向和反向迭代器使用索引\n访问值。即使基础序列发生变异,该索引也将继续向前(或\n向后)前进。仅当遇到 IndexError 或 StopIteration(或当索引降至零以下时),迭代器才会终止。
\n