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 класс является конкретным, если он не объявлен абстрактным.