Python中的typing – 用于继承多个基类的TypeVar

huangapple go评论91阅读模式
英文:

Python typing - TypeVar for something that inherits from multiple base classes

问题

T = TypeVar("T", bound=Union[X, Y])

def foo(x: T) -> None:
    assert isinstance(x, X)
    assert isinstance(x, Y)
英文:

Python's TypeVar allows setting a bound for a type, like so

from typing import TypeVar


class A:
    pass


T = TypeVar("T", bound=A)


def foo(_: T) -> None:
    pass


class B(A):
    pass


class C:
    pass


foo(B())  # OK
foo(C())  # error: Value of type variable "T" of "foo" cannot be "C"

My question is how can I express "any type T where T inherits from X and Y"?

This was my first naive attempt:

from typing import TypeVar


class X:
    pass


class Y:
    pass


class XY(X, Y):
    pass


T = TypeVar("T", bound=XY)


def foo(_: T) -> None:
    pass


class MyClass(X, Y):
    pass


foo(MyClass())  # error: Value of type variable "T" of "foo" cannot be "MyClass"

This doesn't work, because MyClass isn't a subclass of XY, and mypy correctly rejects the code.

In this minimal example I could do class MyClass(XY), but this isn't a good solution for the actual code I'm working with. Consider what happens if there are classes X1, X2, ..., Xn, and I have functions that expect types that inherit from some subset of these. Making a class for each combination would be infeasible, as MyClass would need to inherit from each "combo-class".

Essentially I'm looking for something equivalent to this fictional code:

T = TypeVar("T", bound=(X, Y))  # Not allowed

def foo(x: T):
    assert isinstance(x, X)
    assert isinstance(x, Y)

Any thought's on how this could be done, or achieve something to this effect?

答案1

得分: 1

The only support the current Python typing system has for type hinting multiple inheritance is through a Protocol, where all the bases also have to be Protocols, as documented in PEP-544:

from typing import TypeVar, Protocol

class X(Protocol):
    pass

class Y(Protocol):
    pass

class XY(X, Y, Protocol):
    pass

T = TypeVar("T", bound=XY)

def foo(_: T) -> None:
    pass

class MyClass(X, Y):
    pass

foo(MyClass())

Demo: https://mypy-play.net/?mypy=latest&python=3.11&gist=f392ad6b46ff9b87c1f3e574bc7626c6

英文:

The only support the current Python typing system has for type hinting multiple inheritance is through a Protocol, where all the bases also have be Protocols, as documented in PEP-544:

from typing import TypeVar, Protocol

class X(Protocol):
    pass

class Y(Protocol):
    pass

class XY(X, Y, Protocol):
    pass

T = TypeVar("T", bound=XY)

def foo(_: T) -> None:
    pass

class MyClass(X, Y):
    pass

foo(MyClass())

Demo: https://mypy-play.net/?mypy=latest&python=3.11&gist=f392ad6b46ff9b87c1f3e574bc7626c6

huangapple
  • 本文由 发表于 2023年4月13日 17:36:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76003924.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定