首页 > 解决方案 > 类属性的类型提示

问题描述

我有一个包含许多模型和许多基于类的视图的 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,它是视图中指定模型的实例。我怎样才能做到这一点?谢谢

标签: pythoninheritancetype-hinting

解决方案


您需要使您的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类型别名。这部分是风格上的,部分是务实的。

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

务实地说,当您过度使用包含类型变量的类型别名时,PyCharm 的类型检查器和 mypy 都会有点困难。


推荐阅读