Python类型注解:从抽象基类派生的类实例化对象

4
假设已经创建了一个抽象基类 MembershipClass。有多个类从该抽象基类派生,例如 FirstClassSecondClass 等等。
我希望在一个函数中使用类型注释,该函数接受任何从 MembershipClass 派生的类作为参数。如果派生类数量很少(比如说 2 个),那么应该可以这样实现:
from typing import Union
def MyFunc(membership_obj: Union[FirstClass, SecondClass]) -> None:
   ...

有没有一种方法可以创建一个类型提示,用于 membership_obj,它实际上表示其类型是从 MembershipClass 派生的任何类,而无需在类型注释中指定每个可能的派生类?

我看到了两种可能的解决方案:

  1. TypeVar
from typing import TypeVar
BaseType = TypeVar('BaseType', bound=MembershipClass)
def MyFunc(membership_obj: BaseType) -> None:
   ...

  1. ABC的直接使用
def MyFunc(membership_obj: MembershipClass) -> None:
   ...

这两种方法都可以接受吗?

1个回答

2

看起来这两种解决方案都可以,尽管mypy的信息略有不同。考虑以下示例(我已经内联添加了mypy错误):

from abc import ABC
from typing import TypeVar


class Base(ABC):
    pass


class Sub(Base):
    pass


BaseType = TypeVar("BaseType", bound=Base)


def MyFunc(c: Base) -> None:
    pass


def MyFunc2(c: BaseType) -> None:
    pass


if __name__ == "__main__":
    b = Base()
    s = Sub()

    MyFunc(b)
    MyFunc(s)
    MyFunc(3)  # main.py:30: error: Argument 1 to "MyFunc" has incompatible type "int"; expected "Base"

    MyFunc2(b)
    MyFunc2(s)
    MyFunc2(3) # main.py:34: error: Value of type variable "BaseType" of "MyFunc2" cannot be "int"

话虽如此,我认为第二种方法更易读和直观。我认为 TypeVar 更适合于泛型(这并不是说如果你想要的话就不能使用它)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接