我有一个Web应用程序,其中包含许多模型和许多基于类的视图。大多数代码看起来像这样
<end>
我想要一个属性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?
...
,它是视图中指定模型的实例。我该如何实现?
谢谢
答案 0 :(得分:3)
您需要使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。使用类型别名往往会使/我不太喜欢使用上下文相关的类型。
实用上,当您过多使用包含typevars的类型别名时,PyCharm的类型检查器和mypy都趋于有些挣扎。