Generic - это абстрактный класс в python?

Я пытаюсь создать базовый класс, который работает для любого 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'`

Generic — это способ определить абстрактный класс, содержащий указанные объекты (в данном случае [ModelType, CreateSchemaType, UpdateSchemaType]), или для чего используется generic?

Не уверен, что ваш настоящий вопрос здесь. Общий не обязательно должен быть абстрактным. Также абстрактный класс не обязательно должен быть универсальным. Эти два понятия иногда пересекаются, но они различны. Пожалуйста, будьте более конкретными. Что именно вам не понятно? И задавайте только один вопрос за раз. Также «есть ли лучший способ» крайне расплывчато. Ответ, безусловно, да, независимо от контекста.

Daniil Fajnberg 01.12.2022 21:54

Большое спасибо за ваши наблюдения. В частности, я хотел бы знать в этом случае, что такое использование общего? Это для указания типа переменных, которые должен иметь класс?

Diegol 01.12.2022 21:59
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если ваш вопрос касается цели набора текста. Общий , я бы посоветовал вам прочитать PEP 484 . В нем есть раздел, посвященный определяемым пользователем универсальным классам с некоторыми примерами специально для этого, но ИМХО стоит прочитать весь документ. Если вы не уверены во всей концепции универсальных типов, статьи Википедии о параметрическом полиморфизме и универсальном программировании, возможно, даже стоит просмотреть.

Проще говоря, вы можете использовать базовый класс 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 предоставит вам необходимые инструменты. Вы можете определить абстрактный базовый класс и абстрактные методы, которые должны быть реализованы во всех подклассах. Но я думаю, теперь ясно, что это другая концепция. Идея состоит в том, что абстрактный класс не предназначен для создания экземпляров, только его подклассы.

Я надеюсь, что это поможет указать вам несколько полезных направлений.

Большое спасибо! Это гораздо более полный ответ, чем я мог себе представить. Такие люди, как вы, делают это сообщество мощным инструментом для всех!

Diegol 02.12.2022 00:09

Другие вопросы по теме