假设我有一个愚蠢的功能,比如FizzBuzz:
>>> def FizzBuzz(i):
... if i % 15 == 0:
... return "FB"
... elif i % 3 == 0:
... return "F"
... elif i % 5 == 0:
... return "B"
... else:
... return i
列表:
>>> li=list(range(1,22))
>>> li
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
现在,如果我执行将该函数应用于列表的生成器表达式:
>>> ge=(FizzBuzz(x) for x in li)
>>> ge
<generator object <genexpr> at 0x1063ca3a8>
我可以把它变成一个列表(即运行生成器表达式):
>>> list(ge)
[1, 2, 'F', 4, 'B', 'F', 7, 8, 'F', 'B', 11, 'F', 13, 14, 'FB', 16, 17, 'F', 19, 'B', 'F']
现在假设我执行切片分配而不是分配给单独的名称:
>>> li=list(range(1,22))
>>> li[:]=(FizzBuzz(x) for x in li)
>>> li
[1, 2, 'F', 4, 'B', 'F', 7, 8, 'F', 'B', 11, 'F', 13, 14, 'FB', 16, 17, 'F', 19, 'B', 'F']
您可以看到生成器表达式立即执行。
与map
相同:
>>> map(FizzBuzz, li)
<map object at 0x10640c358>
>>> li[:]=map(FizzBuzz, li)
>>> li
[1, 2, 'F', 4, 'B', 'F', 7, 8, 'F', 'B', 11, 'F', 13, 14, 'FB', 16, 17, 'F', 19, 'B', 'F']
现在假设FizzBuzz
不是一个愚蠢的函数,而是一个需要一段时间的函数,而li
足够大,你想要进行切片赋值。
有没有办法推迟生成器的执行但仍然分配到位? (我确实知道我可以做ge=(f(x) for x in big_list); big_list[:]=list(ge)
这是一种解决方法......)
答案 0 :(得分:1)
显然,(FizzBuzz(x) for x in li)
需要li
在开始运行时仍然“完整”,因为它必须遍历它并获得正确的项目。
那么你想在哪里“分配到位” - 你想到的哪个地方?
将其分配给独立于li
的变量,您将其视为“变通方法”,当然可以。
但是哪里你想把它放在哪里?!
当你准备好运行它之前,它肯定不会在li
的内容上被践踏,因为我们已经确定在生成器开始运行时所述内容必须完整。
您可以使用def
绑定这些内容,例如
def doge(savedli=list(li)):
for x in savedli: yield FizzBuzz(x)
现在,li[:]=doge
会擦除li
的内容,但是仍然会将它们安全地隐藏在doge
(现在设置为li[0]
)中,以便稍后你可以做li[:] = doge()
。但我认为这种更加扭曲的方法没有任何优势。
因此,如果这个答案不能令人满意,请在 的地方说明你想要“分配到位”的发电机,当然要尊重列表原始内容的存在以求生存 直到发电机开始运转为止。