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

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

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

问题

  1. T = TypeVar("T", bound=Union[X, Y])
  2. def foo(x: T) -> None:
  3. assert isinstance(x, X)
  4. assert isinstance(x, Y)
英文:

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

  1. from typing import TypeVar
  2. class A:
  3. pass
  4. T = TypeVar("T", bound=A)
  5. def foo(_: T) -> None:
  6. pass
  7. class B(A):
  8. pass
  9. class C:
  10. pass
  11. foo(B()) # OK
  12. 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:

  1. from typing import TypeVar
  2. class X:
  3. pass
  4. class Y:
  5. pass
  6. class XY(X, Y):
  7. pass
  8. T = TypeVar("T", bound=XY)
  9. def foo(_: T) -> None:
  10. pass
  11. class MyClass(X, Y):
  12. pass
  13. 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:

  1. T = TypeVar("T", bound=(X, Y)) # Not allowed
  2. def foo(x: T):
  3. assert isinstance(x, X)
  4. 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:

  1. from typing import TypeVar, Protocol
  2. class X(Protocol):
  3. pass
  4. class Y(Protocol):
  5. pass
  6. class XY(X, Y, Protocol):
  7. pass
  8. T = TypeVar("T", bound=XY)
  9. def foo(_: T) -> None:
  10. pass
  11. class MyClass(X, Y):
  12. pass
  13. 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:

  1. from typing import TypeVar, Protocol
  2. class X(Protocol):
  3. pass
  4. class Y(Protocol):
  5. pass
  6. class XY(X, Y, Protocol):
  7. pass
  8. T = TypeVar("T", bound=XY)
  9. def foo(_: T) -> None:
  10. pass
  11. class MyClass(X, Y):
  12. pass
  13. 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:

确定