gpt4 book ai didi

python - 解决生成器中的评估时间差异

转载 作者:太空宇宙 更新时间:2023-11-03 15:49:22 25 4
gpt4 key购买 nike

我发现自己遇到了来自 this list 的“评估时间差异”问题今天,我很难解决这个问题。

作为我的问题的简短演示,我制作了无限生成器,它们跳过每个 n 数字,n 来自 [2..5]:

from itertools import count

skip_lists = []
for idx in range(2, 5):
# skip every 2nd, 3rd, 4th.. number
skip_lists.append(x for x in count() if (x % idx) != 0)

# print first 10 numbers of every skip_list
for skip_list in skip_lists:
for _, num in zip(range(10), skip_list):
print("{}, ".format(num), end="")
print()

预期输出:

1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 
1, 2, 4, 5, 7, 8, 10, 11, 13, 14,
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,

实际输出:

1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,

一旦我想起了这个很棒的功能,我就尝试通过将 if 子句变量绑定(bind)到一个常量来“解决”它,该常量将成为 skip_list 的一部分:

from itertools import count

skip_lists = []
for idx in range(2, 5):
# bind the skip distance
skip_lists.append([idx])
# same as in the first try, but use bound value instead of 'idx'
skip_lists[-1].append(x for x in count() if (x % skip_lists[-1][0]) != 0)

# print first 10 numbers of every skip_list
for skip_list in (entry[1] for entry in skip_lists):
for _, num in zip(range(10), skip_list):
print("{}, ".format(num), end="")
print()

但再次:

1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,
1, 2, 3, 5, 6, 7, 9, 10, 11, 13,

除了实际的解决方案之外,我还很想知道为什么我的 hack 不起作用。

最佳答案

idx 的值永远不会被查找,直到你开始迭代生成器(生成器被延迟评估),此时 idx = 4 是最新的迭代值,是模块作用域中存在的内容。

您可以通过将 idx 传递给函数并在每个生成器的评估时间从函数范围读取值,使每个附加的生成器在 idx 中有状态。这利用了生成器表达式的可迭代源在 gen 处求值的事实。 exp 的创建时间,因此该函数在循环的每次迭代中都会被调用,idx安全地存储在函数作用域中:

from itertools import count

skip_lists = []

def skip_count(skip):
return (x for x in count() if (x % skip) != 0)


for idx in range(2, 5):
# skip every 2nd, 3rd, 4th.. number
skip_lists.append(skip_count(idx))

生成器表达式的可迭代源求值说明。 exp 的创建:

>>> (i for i in 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable

你的情况有点棘手,因为排除实际上是在 filter 中完成的,它不会在 gen exp 的创建时间进行评估:

>>> (i for i in range(2) if i in 5)
<generator object <genexpr> at 0x109a0da50>

for 循环和过滤器都需要移动到存储 idx 的范围内的更多原因;不仅仅是过滤器。


换句话说,您可以使用 itertools.islice 而不是您用来打印生成器表达式的 slice 的低效逻辑:

from itertools import islice

for skip_list in skip_lists:
for num in islice(skip_list, 10):
print("{}, ".format(num), end="")
print()

关于python - 解决生成器中的评估时间差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47790212/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com