简体   繁体   中英

I have this code and I don't get why the result of print(su) isn't zero

Help me understand why yield total doesn't comes out as 0 at the first calling!

Since [sumer] passed though [primer] by @coroutine, [su] already met next() in side of primer right?

So I'm guessing the result of print('EX2-1 -',su) should be 0

But the real result turns out to be just showing the address of su, and only after su.send(100) the value comes out as 100

What am I missing??

from functools import wraps
from inspect import getgeneratorstate


def coroutine(func):
   @wraps(func) 
   def primer(*args, **kwargs):
       gen = func()
       next(gen)
       return gen
   return primer

@coroutine
def sumer():
    total = 0
    term = 0
    while True :
        term = yield total
        print('term recieved')
        total += term

su = sumer()
print('EX2-1 -',su)
print(getgeneratorstate(su))
print('EX2-1 -', su.send(100))

su is the generator object itself. If you want to get the current value of total at any point you need to make it yield it, but you can't use next() because this will make term be None which will cause an error. Instead, you need to use .send(0) :

from functools import wraps
from inspect import getgeneratorstate


def coroutine(func):
   @wraps(func) 
   def primer(*args, **kwargs):
       gen = func()
       next(gen)
       return gen
   return primer

@coroutine
def sumer():
    total = 0
    term = 0
    while True :
        term = yield total
        print('term recieved')
        total += term

su = sumer()
print('EX2-1 -', su.send(0))
print(getgeneratorstate(su))
print('EX2-1 -', su.send(100))

Let's go through your code step by step.

The coroutine decorator is gonna return it's inner function which is primer and that's it... So after you apply @coroutine to the sumer , the sumer label is now pointing to the primer function.

Next when you call the primer function in line su = sumer() , it will create a coroutine in line gen = func() then primes it with next(gen) and returns the primed coroutine.

Up until now su is pointing to whatever the primer function returned, which is a generator not the value !

Your problem is exactly here, if the primer returns next(gen) you will get 0 . But that 0 is just skipped and your coroutine is now ready to receive values.

Try to change it to:

from functools import wraps

def coroutine(func):
    @wraps(func)
    def primer(*args, **kwargs):
        gen = func()
        return next(gen)

    return primer


@coroutine
def sumer():
    total = 0
    while True:
        term = yield total
        print('term recieved')
        total += term


su = sumer()
print('EX2-1 -', su)

It is 0 now but not useful anymore. Since su is not the generator anymore, you can't pass it to the getgeneratorstate and also send value to it. It is an integer now.

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