简体   繁体   中英

Why is the behavior of Python generators different when they're being updated in a for loop?

I was playing around with the following code in Python 3.8:

a = range(10)
limits = (5, 3) # order of limits doesn't matter
a = (i for i in a if i > limit[0])
a = (i for i in a if i > limit[1])
print(list(a))

As referenced in the comment, it doesn't matter which limit is being applied first in this case; whether limits = (5, 3) or (3, 5) , the output on the last line is [6, 7, 8, 9] in both cases. However, this is no longer the case with a (seemingly) inconsequential refactor of the code:

a = range(10)
limits = (5, 3) # order of limits matters now?
for limit in limits:
    a = (i for i in a if i > limit)
print(list(a))

With the refactor, if limits = (3, 5) , then the resulting output is [6, 7, 8, 9] , but with limits = (5, 3) , the output equals [4, 5, 6, 7, 8, 9] . It seems like only the final filter is applied in this case; when I ran the following code:

a = range(10)
limits = (4, 3, 2, 1, 0)
for limit in limits:
    a = (i for i in a if i > limit)
print(list(a))

[1, 2, 3, 4, 5, 6, 7, 8, 9] was the output. Can someone explain why this behavior is happening?

In the refactored version, the value of the limit variable is looked up when the generators generate values, not when the generator objects are created.

Since value generation only happens on the last line with list(a) , at this time the value of limit is whatever it was for the last iteration of the loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM