如何设置 class 方法 return 从 class 属性 动态输入
How to set a class method return typing dynamically from a class property
我正在做我的一个宠物项目,发现了这个小问题。我想在基础 class 中使用类型,问题是 class 方法的 return 类型是由 subclasses 设置的字段定义的。这是我的基地 class
class BaseRepository(metaclass=RequiredAttributes('model')):
model = None # The subclasses have to define the this field with a class type.
# All the class methods will return objects of the same
# type as this field.
def get(self, id) -> ??:
# return an object of the type defined in mode
...
class UserRepo(BaseRepository): # subclass
model = User # class type
...
我想将 get
函数的类型设置为与模型字段中定义的对象类型相同。
关于我怎样才能完成这样的事情有什么建议吗?
如果没有元类,这个 passes MyPy, which is correctly able to infer that x
is of type User
. I wasn't able to test it with the metaclass, as I don't have your metaclass definition. The solution uses a parameterised Generic
as a base class, which allows you to then assert to the type-checker that different methods across the class will have the same parameter and return argument types. A similar technique is used in Django's stub files。
N.B。你必须从 typing
模块导入 Type
并且如果你使用 Python <= 3.8.
from typing import Optional, Generic, TypeVar
M = TypeVar('M')
class BaseRepository(Generic[M], metaclass=RequiredAttributes('model')):
model: Optional[type[M]] = None # The subclasses have to define the this field with a class type.
# All the class methods will return objects of the same
# type as this field.
def get(self, id: int) -> M: ...
# return an object of the type defined in mode
class User:
pass
class UserRepo(BaseRepository[User]): # subclass
model = User # class type
x = UserRepo().get(1)
reveal_type(x) # Revealed type is "__main__.User*"
我正在做我的一个宠物项目,发现了这个小问题。我想在基础 class 中使用类型,问题是 class 方法的 return 类型是由 subclasses 设置的字段定义的。这是我的基地 class
class BaseRepository(metaclass=RequiredAttributes('model')):
model = None # The subclasses have to define the this field with a class type.
# All the class methods will return objects of the same
# type as this field.
def get(self, id) -> ??:
# return an object of the type defined in mode
...
class UserRepo(BaseRepository): # subclass
model = User # class type
...
我想将 get
函数的类型设置为与模型字段中定义的对象类型相同。
关于我怎样才能完成这样的事情有什么建议吗?
如果没有元类,这个 passes MyPy, which is correctly able to infer that x
is of type User
. I wasn't able to test it with the metaclass, as I don't have your metaclass definition. The solution uses a parameterised Generic
as a base class, which allows you to then assert to the type-checker that different methods across the class will have the same parameter and return argument types. A similar technique is used in Django's stub files。
N.B。你必须从 typing
模块导入 Type
并且如果你使用 Python <= 3.8.
from typing import Optional, Generic, TypeVar
M = TypeVar('M')
class BaseRepository(Generic[M], metaclass=RequiredAttributes('model')):
model: Optional[type[M]] = None # The subclasses have to define the this field with a class type.
# All the class methods will return objects of the same
# type as this field.
def get(self, id: int) -> M: ...
# return an object of the type defined in mode
class User:
pass
class UserRepo(BaseRepository[User]): # subclass
model = User # class type
x = UserRepo().get(1)
reveal_type(x) # Revealed type is "__main__.User*"