Pylint W0223: 方法...在类...中是抽象的但没有被重写
Pylint会对抽象类的子类产生这个错误,即使这些子类没有被实例化,并且它们的方法在具体的子类中确实被重写了。为什么Pylint会认为我的抽象子类是要变成具体类的呢?我该怎么做才能消除这个警告,而不需要直接在配置文件中把它完全关闭呢?
3 个回答
0
我同意Michal的看法,你应该使用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中,如果一个类没有被声明为抽象类,它就是具体类,所以不会有最终警告。
5
为了消除错误的 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)问题。
29
出于某种原因,pylint认为这个类不是抽象类(目前的检测方式是查看是否有方法抛出NotImplementedError)。在模块的顶部或者类的顶部添加一个注释,比如#pylint: disable=W0223
,可以解决这个问题(这个注释只会在这个模块或这个类中生效)。