简体   繁体   中英

Python generator confusing behavior

This question arises when I read a generator tutorial https://realpython.com/introduction-to-python-generators/ . is_palindrome(101) returns True, but the code didn't print 101. I debugged and saw yield 101 led the execution back to the main for loop, which immediately went back to the generator, which is very confusing. The generator yields 101, hence it should be an element of for j in pal_gen: , isn't it?

def is_palindrome(num):
    # Skip single-digit inputs
    if num // 10 == 0:
        return False
    temp = num
    reversed_num = 0

    while temp != 0:
        reversed_num = (reversed_num * 10) + (temp % 10)
        temp = temp // 10

    if num == reversed_num:
        return True
    else:
        return False

def infinite_palindromes():
    num = 0
    while True:
        if is_palindrome(num):
            i = (yield num)
            if i is not None:
                num = i
        num += 1

if __name__=='__main__':        
    pal_gen = infinite_palindromes()
    for j in pal_gen:
        print(f'j={j}')
        digits = len(str(j))
        if digits == 5:
            pal_gen.close()        
        pal_gen.send(10 ** (digits))

Currently the output is:

j=11
j=111
j=1111
j=10101
Traceback (most recent call last):
  File "generator.py", line 33, in <module>
    pal_gen.send(10 ** (digits))
StopIteration

You'll notice it is skipping one between each. 101 is missing, 1001 is missing. 10001 is missing. I'm pretty sure send leads the generator to run to the next yield statement. For example, use the following code:

if __name__=='__main__':
    pal_gen = infinite_palindromes()
    for j in pal_gen:
        print('j={}'.format(j))
        digits = len(str(j))
        if digits == 5:
            pal_gen.close()
        print(pal_gen.send(10 ** (digits)))

This will print out the missing values between the "j's":

j=11
101
j=111
1001
j=1111
10001
j=10101

Consider redoing your for statement with a while :

if __name__=='__main__':
    pal_gen = infinite_palindromes()
    j=next(pal_gen)
    digits=0    
    while digits<5:  
        print('j={}'.format(j))
        digits = len(str(j))
        j = pal_gen.send(10 ** (digits))
    else:
        pal_gen.close()

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