为了账号安全,请及时绑定邮箱和手机立即绑定

变量引用了错误的迭代器,即使在确认重新分配之后

变量引用了错误的迭代器,即使在确认重新分配之后

胡说叔叔 2021-11-09 14:34:21
我有以下循环重新分配给迭代器变量:currentPrime = Nonesieve = iter(range(2, 10))while True:    try:        # The first value should be prime.        currentPrime = next(sieve)    except StopIteration:        # Stop when sieve is empty.        print(currentPrime)        break    print(currentPrime)    # Filter out all multiples of currentPrime.    sieve = (x for x in sieve if x % currentPrime)    #print(tuple(sieve))即使我在循环的每次迭代中都应用了一个过滤器,输出也会贯穿整个范围:234567899如果我取消对最后一个print调用的注释,我会看到(3, 5, 7, 9),这意味着过滤器和赋值可以sieve正常工作,但是next(sieve)调用以某种方式访问了没有变量指向的原始迭代器。知道这里发生了什么吗?我正在使用 Python 3.7.0。
查看完整描述

2 回答

?
UYOU

TA贡献1878条经验 获得超4个赞

正如 user2357112 所说,“currentPrime在使用时查找,而不是在生成器创建时查找。”


一种解决方案是使用filterlambda 来定位 的当前值currentPrime。请注意 lambda 如何使用默认参数来创建局部变量:


currentPrime = None

sieve = iter(range(2, 10))

while True:

    try:

        # The first value should be prime.

        currentPrime = next(sieve)

    except StopIteration:

        # Stop when sieve is empty.

        print(currentPrime)

        break

    # Filter out all multiples of currentPrime.

    sieve = filter(lambda x, prime=currentPrime: x % prime, sieve)


查看完整回答
反对 回复 2021-11-09
?
翻阅古今

TA贡献1780条经验 获得超5个赞

如果我没记错的话,这里有一堆发电机。

会发生什么(TL;DR:所有生成器都引用一个 currentPrime 实例并引用惰性):

  1. 从范围迭代器中获取值 2。

  2. 创建生成器表达式 (A)。现在变量 currentPrime = 2 并且不是免费的(未关闭)。发电机消耗剩余范围(3..9)。

  3. 从生成器 A 获取值 3(3 % 2 为 True)

  4. 创建生成器表达式 (B)。两个发电机 (A, B) 的变量 currentPrime = 3 。发电机消耗发电机 A (4..9) 的剩余部分。

  5. 从生成器 B 中获取值 4。参见:next() → B.next(A) → A 产生 4(A 检查:4 % 3为真),然后 B 检查 4 % 3 为真。

  6. 创建生成器表达式 (C) ... 等等。

生成器中的变量不在闭包中,请参阅:

>>> a = 5

>>> gen = (a for i in range(3))

>>> a = 3

>>> list(gen)

[3, 3, 3]


查看完整回答
反对 回复 2021-11-09
  • 2 回答
  • 0 关注
  • 134 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信