我正在尝试创建一个基类,它适用于应用程序中的任何CRUD,我看到了以下实现:
ModelType = TypeVar("ModelType", bound=Base)
CreateSchemaType = TypeVar("CreateSchemaType", bound=BaseModel)
UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel)
class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
def __init__(self, model: Type[ModelType]):
"""CRUD object with default methods to Create, Read, Update,
Delete (CRUD).
**Parameters**
* `model`: A SQLAlchemy model class
* `schema`: A Pydantic model (schema) class
"""
self.model = model
'...crud methods'`
泛型是定义抽象类的一种方法,包含指定的对象(在本例中是ModelType、CreateSchemaType、UpdateSchemaType),或者泛型的用途是什么?
发布于 2022-12-01 21:34:01
如果你的问题是关于typing.Generic
的目的,我建议你阅读佩普484。它有一个专门讨论用户定义的泛型类的部分,并提供了一些专门用于此的示例,但整个文档值得阅读IMHO。如果您不确定泛型类型的整个概念,维基百科关于参数多态性和通用程序设计的文章甚至值得浏览。
简单地说,您可以使用Generic
基类以泛型方式定义自己的类,即针对一个或多个类型参数进行参数化。这些类型参数是通过typing.TypeVar
构造的。值得注意的是,在大多数情况下,这些事情只与类型安全相关,而Python本身并没有真正强制这样做。相反,静态类型检查器(大多数IDE都有内置的)处理这些事情。
至于您的示例,完全有可能以通用的方式定义类,从而改进您自己的编码体验,因为IDE可能会给您提供有用的自动建议和警告。如果您在整个类的其他地方使用类型变量,这才会真正变得有用。示例:
from typing import Generic, TypeVar
class Base:
pass
ModelType = TypeVar("ModelType", bound=Base)
class CRUDBase(Generic[ModelType]):
def __init__(self, model: type[ModelType]):
self.model = model
def get_model_instance(self) -> ModelType:
return self.model()
class Sub(Base):
def foo(self) -> None:
print("hi mom")
if __name__ == "__main__":
crud_a = CRUDBase(Sub)
crud_b = CRUDBase(Base)
a = crud_a.get_model_instance()
b = crud_b.get_model_instance()
a.foo()
b.foo() # error
像mypy
这样的好类型检查器会知道,a
是Sub
类型,因此有foo
方法,而b
是Base
类型,因此没有。从我们注释CRUDBase
的方式,它就会知道这一点。
例如,PyCharm与此作斗争(不知道原因)。幸运的是,我们可以通过显式类型注释来帮助它,因为我们将CRUDBase
定义为泛型类型:
...
crud_a: CRUDBase[Sub] = CRUDBase(Sub)
crud_b: CRUDBase[Base] = CRUDBase(Base)
a = crud_a.get_model_instance()
b = crud_b.get_model_instance()
a.foo()
b.foo() # PyCharm marks `foo` and complains
注意,到目前为止,对于我们的CRUDBase
还没有什么特别的“抽象”。它是完全独立的,并且像这样运作(虽然还不是很有用)。
如果您希望类是一个抽象基,而不是直接实例化,abc
模块将为您提供所需的工具。您可以在它上定义一个抽象基类和抽象方法,所有子类都必须实现它。但我认为现在很清楚,这是一个不同的概念。其思想是抽象类不是要实例化的,而是它的子类。
我希望这能帮助你指出一些有用的方向。
https://stackoverflow.com/questions/74647999
复制相似问题