Search code examples
pythondecoratorcoroutineyield

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))

Solution

  • 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.