Search code examples
pythongeneratorpython-typing

Type-hinting a generator: send_type Any or None?


I have a generator that does not use send() values. Should I type its send_value as Any or None?

import typing as t

def pi_generator() -> t.Generator[int, ???, None]:
    pi = "3141592"
    for digit in pi:
        yield int(digit)

pi_gen = pi_generator()
next(pi_gen)  # 3
pi_gen.send('foo')  # 1
pi_gen.send(pi_gen)  # 4

Reasons I see for Any:

  • The generator works perfectly fine with send() for any type, so if somebody had a reason to use .send(1) with this generator, it's totally fine.
  • Methods' arguments' types should be general, and .send(x: Any) is more general than .send(x: None).

Reasons I see for None:

  • Return types should be specific, and "Generator that never uses send" is a more specific type than "Any kind of generator".
  • If someone is using .send() to this generator, it's likely they're misunderstanding what it does and the type hint should inform them.

Solution

  • Quoting the docs for typing.Generator:

    If your generator will only yield values, set the SendType and ReturnType to None:

    def infinite_stream(start: int) -> Generator[int, None, None]:
       while True:
           yield start
           start += 1
    

    Setting SendType to None is the recommended way to communicate that the generator does not expect callees to send() values.