Python 使用处理程序工厂时无法推断子类的静态类型

Python can't infer static type of subclass when using a handler factory

我想使用通用的 HandlerFactory class,就像 here 中描述的那样(参见 解决方案 2:元编程)。

让我举个例子:

假设我们有以下 classes:

class Person:
    name: str

@PersonHandlerFactory.register
class Mark(Person):
    name = "Mark"
    job = "scientist"

@PersonHandlerFactory.register
class Charles(Person):
    name = "Charles"
    hobby = "football"

您可能已经注意到子classes 包含一个装饰器。此装饰器用于将这些 classes 注册到以下 PersonHandlerFactory class,其中 returns 一个特定的 class 给定的人名:

from typing import Dict, Type

class PersonHandlerFactory:
    handlers: Dict[str, Type[Person]] = {}

    @classmethod
    def register(cls, handler_cls: Type[Person]):
        cls.handlers[handler_cls.name] = handler_cls
        return handler_cls

    @classmethod
    def get(cls, name: str):
        return cls.handlers[name]

如您所见,我使用了 Type[Person] 类型,因为我希望此方法用于 Person.

的任何子 class

但不知何故 Python 将任何子实例的静态类型class 解释为 class Parent:

mark = Mark()  # Static type of 'mark' is 'Person' :S
print(mark.job)  # Python can't find the type of 'job'

我不想为 Mark | Charles 更改 Type[Person] 因为 class PersonHandlerFactory 不应该知道 [=] 的子 class 17=].

使用边界 TypeVar,这样可以推断出正确的子class。

from typing import Dict, Type, TypeVar


class Person:
    name: str


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


class PersonHandlerFactory:
    handlers: Dict[str, Type[Person]] = {}

    @classmethod
    def register(cls, handler_cls: Type[T]) -> Type[T]:
        cls.handlers[handler_cls.name] = handler_cls
        return handler_cls

    @classmethod
    def get(cls, name: str):
        return cls.handlers[name]


@PersonHandlerFactory.register
class Mark(Person):
    name = "Mark"
    job = "scientist"


mark = Mark()  # Static type of 'mark' is 'Mark' :)

PersonHandlerFactory.get 返回的 class 将始终被推断为 Type[Person]