我发现自己在评估时间不一致的情况下遇到了问题'今天来自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
子句变量绑定到一个常量,该常量将成为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,
除了实际解决方案之外,我还想了解为什么我的黑客没有工作。
答案 0 :(得分:3)
在开始迭代生成器(懒惰地评估生成器)之前,永远不会查找idx
的值,此时idx = 4
最新的iteratee值是模块范围中存在的值
您可以通过将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))
生成器表达式在gen的可迭代源评估的图示。 exp的创作:
>>> (i for i in 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
你的情况有点棘手,因为排除实际上是在过滤器中完成的,而这个过滤器在创建时没有得到评估:
>>> (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()