Automatically advancing a bi-directional generator to the point of accepting a non-None value?

Dieter Maurer dieter at handshake.de
Sun Nov 22 13:22:23 EST 2020


Go Luhng wrote at 2020-11-21 14:30 -0500:
>Suppose we write a very simple bi-directional generator in Python:
>
>    def share_of_total():
>        s = 0
>        new_num = 0
>        while True:
>            new_num = yield new_num / (s or 1)
>            s += new_num
>
>    share_calculator = share_of_total()
>    next(share_calculator)  # Without this we get the TypeError
>
>    for num in [1, 2, 3]:
>        print(share_calculator.send(num))
>
>This generator just accepts a number and yields a float representing
>its share of the sum of all previously provided numbers.
>
>We would ideally like to just use it immediately as follows:
>
>    share_calculator = share_of_total()
>    print(share_calculator.send(num))
>
>However, this causes `TypeError: can't send non-None value to a
>just-started generator`. All users of the `share_of_total()` must
>remember to execute `next(share_calculator)` before the generator is
>usable as intended.

When you want to automate things, you write a function.

In your case, you have a generator function
and you want that this generator function is called,
then `next` is applied to the resulting generator;
the resulting generator is what you actually want.

>From this description, it should be easy to define a function
which does precisely this for you.

If you find that you regularly want to automate the initial `next`,
you can implement your function as a so called "decorator",
say `auto_next`. Then you can define generator functions
with automatic `next` via:

@auto_next
def gen_fun(...): ...


More information about the Python-list mailing list