【问题标题】:Type hints for class attribute类属性的类型提示
【发布时间】:2019-02-20 01:33:57
【问题描述】:

我有一个包含许多模型和许多基于类的视图的 Web 应用程序。大部分代码是这样的

from typing import TypeVar, Type

M = TypeVar('M', bound='Model')
TypeModel = Type[M]


# ----------  models
class Model:
    @classmethod
    def factory(cls: TypeModel) -> M:
        return cls()


class ModelOne(Model):
    def one(self):
        return


class ModelTwo(Model):
    def two(self):
        return


# ----------  views
class BaseView:
    model: TypeModel

    @property
    def obj(self) -> M:
        return self.model.factory()

    def logic(self):
        raise NotImplementedError


class One(BaseView):
    model = ModelOne

    def logic(self):
        self.obj.  # how can i get suggest of methods of ModelOne here?
        ...


class Two(BaseView):
    model = ModelTwo

    def logic(self):
        self.obj.  # how can i get suggest of methods of ModelTwo here?
        ...

我想要一个属性obj,它是视图中指定模型的实例。我怎样才能做到这一点? 谢谢

【问题讨论】:

    标签: python inheritance type-hinting


    【解决方案1】:

    您需要使您的BaseView 类相对于M 通用。所以,你应该这样做:

    from typing import TypeVar, Type, Generic
    
    M = TypeVar('M', bound='Model')
    
    # Models
    
    class Model:
        @classmethod
        def factory(cls: Type[M]) -> M:
            return cls()
    
    class ModelOne(Model):
        def one(self):
            return
    
    class ModelTwo(Model):
        def two(self):
            return
    
    # Views
    
    # A BaseView is now a generic type and will use M as a placeholder.
    class BaseView(Generic[M]):
        model: Type[M]
    
        @property
        def obj(self) -> M:
            return self.model.factory()
    
        def logic(self):
            raise NotImplementedError
    
    # The subclasses now specify what kind of model the BaseView should be
    # working against when they subclass it.
    class One(BaseView[ModelOne]):
        model = ModelOne
    
        def logic(self):
            self.obj.one()
    
    class Two(BaseView[ModelTwo]):
        model = ModelTwo
    
        def logic(self):
            self.obj.two()
    

    注意:我摆脱了您的 TypeModel 类型别名。这部分是风格上的,部分是务实的。

    在风格上,当我查看类型签名时,我希望能够立即确定它是否使用泛型/类型变量。使用类型别名往往会掩盖这一点/我真的不喜欢使用上下文相关类型。

    实际上,当您过度使用包含 typevar 的类型别名时,PyCharm 的类型检查器和 mypy 都会有点困难。

    【讨论】:

    • 感谢您的回答!它有效,但在这种情况下,我需要编写我使用 2 次的模型。如果我将模型属性更改为其他模型类,建议中不会提及,但对我来说没关系。
    猜你喜欢
    • 2021-12-14
    • 2013-11-22
    • 2019-03-26
    • 2022-12-19
    • 2016-09-12
    相关资源
    最近更新 更多