我想使用这里描述的通用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]