Pylint W0223: метод... является абстрактным в классе... но не переопределяется

Pylint генерирует эту ошибку для подклассов абстрактного класса, даже когда сами эти подклассы не создаются, а методы переопределяются в конкретных подклассах. Почему Pylint думает, что мои абстрактные подклассы должны быть конкретными? Как я могу закрыть это предупреждение, не вытащив молоток и не отключив его вообще в файле rc?

3 ответа

Решение

По некоторым причинам Pylint считает, что класс не является абстрактным (текущее обнаружение выполняется путем проверки метода, который вызывает NotImplementedError). Добавление комментария как #pylint: disable=W0223 в верхней части модуля (для отключения только в этом модуле) или класса (только в этом классе), нужно сделать свое дело.

Чтобы заткнуть неправду abstract-methodпредупреждение, вы можете реализовать абстрактные классы с помощью abc.ABCсуперкласс вместо использования abc.ABCMeta метакласс.

Например, этот код вызовет предупреждение:

      from abc import ABCMeta, abstractmethod


class Parent:
    __metaclass__ = ABCMeta

    @abstractmethod
    def do_something(self):
        pass


class Child(Parent):
    __metaclass__ = ABCMeta

но этого не будет:

      from abc import ABC, abstractmethod


class Parent(ABC):

    @abstractmethod
    def do_something(self):
        pass


class Child(Parent, ABC):
    pass

Осторожность! С суперклассом ABC и множественным наследованием вы должны остерегаться потенциальных проблем с порядком разрешения методов (MRO).

Я согласен с Михаль, что вы должны использовать ABCMeta. Я думаю, что то, как оно используется в этом примере, теперь считается лучшим способом его использования.

      from abc import ABCMeta, abstractmethod


class Bird( metaclass=ABCMeta ) :
    '''It's a bird'''

    def __init__(self, name : str ) :
        self._name = name

    @abstractmethod
    def talk(self) :
        '''Talk as as appropriate'''

    @abstractmethod
    def walk(self) :
        ...

# No warning here. The abstract method walk is inherited,
# but this class is declared abstract, so that's ok.
class Duck( Bird, metaclass=ABCMeta ) :
    '''Talks like a duck'''
    def talk(self) :
        return "quack"

# Pylint warns here. The abstract method walk is inherited.
# This class is not declared abstract, but it is abstract because
# it has inherited an abstract method.
class Mallard( Duck ) :
    '''It's really just a Duck, but concrete'''


def main() :
    d = Duck( "Donald" ) # Pylint warns here because Duck is abstract
    m = Mallard( "Moe" ) # Pylint warns here because Mallard is abstract
    # even though it was not declared as such.

Этот стиль очень похож на Java в том смысле, что абстрактные классы должны быть объявлены как таковые. Единственное отличие состоит в том, что в Java вы не получаете окончательное предупреждение, потому что в Java класс является конкретным, если он не объявлен абстрактным.

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