pythonfunctoolssingle-dispatch

Does python functools.singledispatch work with Generator type?


I extended the example at https://docs.python.org/3/library/functools.html#functools.singledispatch by adding a registration for generator type

from functools import singledispatch
from typing import Generator

@singledispatch
def fun(arg, verbose):
    if verbose:
        print("Let me just say,", end=" ")
    print(arg)

@fun.register
def _(arg: list, verbose):
    if verbose:
        print("Enumerate this:")
    for i, elem in enumerate(arg):
        print(i, elem)

# NEW CODE BELOW

@fun.register
def _(arg: Generator, verbose):
    if verbose:
        print("Enumerate this:")
    for i, elem in enumerate(arg):
        print(i, elem)

fun([3,4,5], verbose=True)
fun((i for i in range(6, 10)), verbose=True)

while it works with list, it doesn't seem to work with generator with error like

    raise TypeError(
TypeError: Invalid annotation for 'arg'. typing.Generator is not a class.

Is it expected that singledispatch does not work with generator?


Solution

  • typing.Generator is a type hint, not a type. You need types.GeneratorType.

    from types import GeneratorType
    
    @fun.register
    def _(arg: GeneratorType, verbose):
        if verbose:
            print("Enumerate this:")
        for i, elem in enumerate(arg):
            print(i, elem)

    Objects are not considered instances of type hints according to isinstance, which is what singledispatch uses to decide which function to use for a given argument. With this change, you'll get the expected output

    $ python3 tmp.py
    Enumerate this:
    0 3
    1 4
    2 5
    Enumerate this:
    0 6
    1 7
    2 8
    3 9