最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - Cannot use None as TypeVar constraint? - Stack Overflow

programmeradmin1浏览0评论

Using TypeVar one can annotate functions like:

def f[T: (str, int)](x:T) -> T:
    if isinstance(x, int):
        return 0
    return x

and type checkers will be happy. However it does not work for a None constraint.

def f[T: (str, None)](x:T) -> T:
    if x is None:
        return None
    return x

gives the error

Type "None" is not assignable to type "T@f".

Why is this not possible? Is there a way to achieve this with TypeVars or does one have to use overloads?

The examples used to say return 'a', which would raise a valid error from the type checker. This was an oversight I made while trimming down the example for this question.

Also it is indeed something that I ran into with pyright, not mypy (mypy doesn't complain).

Using TypeVar one can annotate functions like:

def f[T: (str, int)](x:T) -> T:
    if isinstance(x, int):
        return 0
    return x

and type checkers will be happy. However it does not work for a None constraint.

def f[T: (str, None)](x:T) -> T:
    if x is None:
        return None
    return x

gives the error

Type "None" is not assignable to type "T@f".

Why is this not possible? Is there a way to achieve this with TypeVars or does one have to use overloads?

The examples used to say return 'a', which would raise a valid error from the type checker. This was an oversight I made while trimming down the example for this question.

Also it is indeed something that I ran into with pyright, not mypy (mypy doesn't complain).

Share Improve this question edited Mar 5 at 16:28 TylerH 21.1k79 gold badges79 silver badges114 bronze badges asked Mar 3 at 13:08 jdoejdoe 311 silver badge4 bronze badges 5
  • because when you return None, that's returning a value of type NoneType, not the type None itself. This doesn't match the constraint requirement for T – Bhargav Commented Mar 3 at 13:13
  • If I run the above code in Python 3.12, I don't get any error, with neither of the two snippets. I can also call the functions and don't see any issues. – Ulrich Eckhardt Commented Mar 3 at 13:15
  • Yes same here @UlrichEckhardt when i checked with type checker i able to reproduce this issue - pip install mypy >> mypy file.py – Bhargav Commented Mar 3 at 13:21
  • @UlrichEckhardt Running the code isn't the issue. – chepner Commented Mar 3 at 13:40
  • Exactly that is the info missing from the question! – Ulrich Eckhardt Commented Mar 3 at 14:52
Add a comment  | 

1 Answer 1

Reset to default 3

This is either a bug or a limitation of Pyright/Pylance, which is the type checker in question.

x is None adds a condition on the original type variable T, causing x to be of type None* within the if block. To oversimplify things, None* can be understood as "some subtype of None and T".

(playground)

def f[T: (str, None)](x: T) -> T:
    if x is None:
        reveal_type(x)  # None*
        return None

    reveal_type(x)  # str*
    return 'a'

In reality, None/NoneType is a final type, so its only subtype is itself. Pyright doesn't understand this well enough, and so it wrongly considers None not to be assignable to T, which at the time is None*.

发布评论

评论列表(0)

  1. 暂无评论