python - 如何设置类方法从类属性中动态返回类型
问题描述
我在我的一个宠物项目中工作,发现了这个小问题。我想在基类中使用类型,问题是类方法的返回类型是由子类设置的字段定义的。这是我的基类
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
函数的类型设置为与模型字段中定义的对象类型相同。
关于如何完成这样的事情有什么建议吗?
解决方案
如果没有元类,这将通过 MyPy,它能够正确推断出x
type User
。我无法使用元类对其进行测试,因为我没有您的元类定义。该解决方案使用参数化Generic
作为基类,它允许您向类型检查器断言跨类的不同方法将具有相同的参数和返回参数类型。Django 的存根文件中使用了类似的技术。
注意如果您使用 Python <= 3.8,则必须Type
从typing
模块导入并使用Optional[Type[M]]
而不是注释。Optional[type[M]]
model
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*"
推荐阅读
- javascript - 我正在将“Select2”安装到我的下拉列表框中,它适用于所有框,但表格中的框除外
- twig - 如何在 OpenCart 中删除客户帐户导航链接
- google-cloud-platform - 通过 gcloud cli 启用 Google Cloud Shell “增强”模式
- php - Laravel 正确设置 slug
- python - 无法在 Scapy 中发送 DNS 回复
- listview - 从 ListView1 中的一行复制的数据未出现在 ListView2 中
- php - 在 Laravel 中验证 2 个数字的幂
- android - 在 Android Studio 3.3.1 中导入旧项目后出错
- socket.io - 即使我没有为它分配任何路由器,如何从我的服务器下载 socket.io
- python - 在 Python 中使用 FlannBasedMatcher 的 DMatch 类中的 imgIdx 出现问题