TypeVar and assignment expresion

Viewed 94

I used assignment expression (aka walrus operator, defined in PEP 572) to define a type T. It seemed an elegant solution, but apparently mypy does not agree.

For the following code:

# Python 3.10.4

from collections.abc import Sequence
from typing import TypeVar

def foo(seq: Sequence[T := TypeVar('T')]) -> T:
    return seq[0]

mypy reports:

error: Invalid type comment or annotation
error: Name "T" is not defined

Is walrus somehow forbidden with TypeVar?

2 Answers

This is really bad idea.

Suppose you have annotations future imported - then this is just a long string, no assignment happens. Suppose you want then to cast(T, something) in function body. If mypy accepts this, it misses runtime error:

NameError: name "T" is not defined

So in this case PEP563 changes behavior of your code.

from __future__ import annotations

from collections.abc import Sequence
from typing import TypeVar


def foo(seq: Sequence[T := TypeVar('T')]) -> T:
    return cast(T, seq[0])

You could cast('T', ...) instead, but this is not-really-annotations-only case.

Starting with python 3.12 (assuming that PEP695 is accepted) it will be possible to use even more elegant and powerful syntax with square brackets that will replace TypeVar:

from typing import Callable

def func[**P, R](cb: Callable[P, R], *args: P.args, **kwargs: P.kwargs) -> R:
    ...
Related