Типобезопасные абстрактные атрибуты в Python с Pylance

Я последовал этому ответу для Python 3.3:

class Abstract(ABC):
    @property
    @abstractmethod
    def title(self) -> str: ...

class Concrete(Abstract):
    title = "Test" # pylance error

Однако в Concrete я получаю ошибку pylance:

Expression of type "Literal['Test']" cannot be assigned to declared type "property"
"Literal['Test']" is incompatible with "property"

Можно ли указать абстрактный атрибут в абстрактном родительском классе, чтобы его можно было переопределить буквальным значением в наследующем классе?

Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Итак, есть несколько разных вариантов в зависимости от конкретного использования. Если вы хотите определить тип атрибута в абстрактном классе, это можно сделать так:

class Abstract(ABC):
    title: str

class Concrete(Abstract):
    title = "test"

Предполагается, что значение title может меняться через Concrete, а «test» — это просто значение по умолчанию.

Однако может оказаться, что вам нужна переменная класса. Это значение будет установлено только конкретным классом и не будет обновляться методами:

from typing import ClassVar

class Abstract(ABC):
    title: ClassVar[str]

class Concrete(Abstract):
    title = "test"

Подробности смотрите здесь. Обратите внимание, что ни один из этих параметров не требует переопределения атрибута, как и свойств, но это именно так и работает. Надеюсь это поможет!

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

Этот код относительно(?) хорош: вы объявляете протокол Abstract, который, как минимум, требует атрибута title только для чтения типа str. Ваш Concrete удовлетворяет этому требованию. Более того, это на самом деле известный рецепт.

Соответствующий pyrightбилет проливает больше света на эту проблему. Разница заключается в доступе к классу: Abstract означает, что доступ из класса даст объект property, но Concrete предоставляет простой str. Это различие может быть важным в некоторых случаях самоанализа или метапрограммирования.

Я не согласен здесь с Эриком Траутом (сегодня открою заявку, чтобы подробнее рассказать об этом — спасибо, что обратили на это мое внимание!), потому что такое поведение, по-видимому, противоречит рекомендациям PEP-544 (с использованием базы Protocol вместо ABC в вашем примере не меняет вывод пирайта):

Чтобы определить переменную протокола, доступную только для чтения, можно использовать (абстрактное) свойство.

mypy принимает ваш код как есть (см. рецепт выше и игровая площадка). Если вы хотите удовлетворить pyright, вам следует либо переопределить свойство, либо добавить комментарий для игнорирования, либо поискать обходные пути. Я бы предпочел # type: ignore прокомментировать исключительно потому, что считаю это ошибкой проверки типов, но решать вам.

Спасибо - есть надежда, что PEP 729 разрешит эти проблемы с типизацией разумным образом.

Matija Sirk 19.04.2024 07:08

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