【问题标题】:How to set a class method return typing dynamically from a class property如何设置类方法从类属性动态返回类型
【发布时间】:2021-10-19 10:54:34
【问题描述】:

我正在从事我的一个宠物项目,发现了这个小问题。我想在基类中使用类型,问题是类方法的返回类型是由子类设置的字段定义的。这是我的基类

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 函数的类型设置为与模型字段中定义的对象类型相同。

有什么建议可以让我完成这样的事情吗?

【问题讨论】:

标签: python python-3.x type-hinting python-typing


【解决方案1】:

没有元类,这个passes MyPy 能够正确推断出xUser 类型。我无法使用元类对其进行测试,因为我没有您的元类定义。该解决方案使用参数化的Generic 作为基类,然后您可以向类型检查器断言该类中的不同方法将具有相同的参数和返回参数类型。 Django 的stub files 中使用了类似的技术。

注意如果您使用 Python typing 模块导入 Type 并使用 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*"

【讨论】:

    猜你喜欢
    • 2021-12-27
    • 2020-11-11
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多