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



我想使用这里描述的通用HandlerFactory类(参见解决方案2:元编程)) .

让我举个例子:

假设我们有以下类:

class Person:
name: str
@PersonHandlerFactory.register
class Mark(Person):
name = "Mark"
job = "scientist"
@PersonHandlerFactory.register
class Charles(Person):
name = "Charles"
hobby = "football"

你可能已经注意到子类包含一个装饰器。该装饰器用于将这些类注册到以下PersonHandlerFactory类中,该类返回给定人名的特定类:

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的任何子类。

但是Python将任何子类的实例的静态类型解释为类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],因为PersonHandlerFactory类不应该知道Person的子类。

使用绑定的TypeVar,这样可以推断出正确的子类。

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返回的类总是被推断为Type[Person]

最新更新