Why are single type constraints disallowed in Python?

Suppose you want to constrain a type variable to implement a certain interface. You might write something like so:

from typing import TypeVar, Callable

T = TypeVar('T', Callable)

class Foo(Generic[T]):
    ...

>> TypeError: A single constraint is not allowed

Why is Python unhappy about this use of type constraints? PEP 484 and the Python source code are unhelpful in this regard.

Note: in my particular case I am interested in constraining a type variable to implement an abstract base class, but the principle is the same.


Solution 1:

You’re looking for bound:

T = TypeVar('T', bound=Callable)

From the docs:

a type variable may specify an upper bound using bound=<type>. This means that an actual type substituted (explicitly or implicitly) for the type variable must be a subclass of the boundary type, see PEP 484.

TypeVar(name, *args) means that the type has to be one of args, so all instances of T would just be replaceable by Callable if T = TypeVar('T', Callable) were allowed.

You should be able to see the difference here (though I didn’t actually try it, heh):

from typing import Generic, TypeVar, Callable

T = TypeVar('T', Callable, bool)

class Foo(Generic[T]):
    value: T

    def __init__(self, value: T) -> None:
        self.value = value

class Bar:
    baz = 5

    def __call__(self):
        pass

f = Foo(Bar())
print(f.value.baz)  # doesn’t typecheck because f.value is only a Callable