[Python] Type narrowing using is for TypeVar in generic class

Discussão em 'Python' iniciado por Stack, Maio 4, 2025.

  1. Stack

    Stack Membro Participativo

    I am working with a generic class in python. The corresponding TypeVar is restricted to a finite amount of (invariant) types. Because it is of some importance what exact type it is at runtime, I specify the type at initialization.

    Later, I have some code where I want to narrow to certain types. Because I want to narrow to this specific type, the natural way seems to use [stored_type] is [desired_type]. Unfortunately, mypy as well as pyright do not perform any narrowing.

    However, if I use isinstance([stored_type], type([desired_type]), it narrows as intended. Also, a similar case where I use a Union instead, the narrowing using is works.

    I am currently using isinstance because it works for the type checker, but as far as I know is provides the stronger check here and is what I actually want.

    Is there a good reason for the current behaviour? Why is the narrowing with is less strict than with isinstance?

    from typing import reveal_type

    class MyClass1:
    def __init__(self):
    pass

    class MyClass2:
    def __init__(self, arg: int):
    pass

    class MyGeneric[V: (MyClass1, MyClass2)]:
    def __init__(self, member_type: type[V]):
    if member_type is MyClass1:
    reveal_type(member_type) # type[V@MyGeneric]

    if isinstance(member_type, type(MyClass1)):
    reveal_type(member_type) # type[MyClass1]*

    def mymethod(self, member_type: type[MyClass1] | type[MyClass2]):
    if member_type is MyClass1:
    reveal_type(member_type) # type[MyClass1]

    Continue reading...

Compartilhe esta Página