首页 > 解决方案 > Python中有没有办法(甚至是要求)来表示抽象的中间类?

问题描述

考虑以下一组类:

from abc import ABC, abstractmethod

class GrandParent(ABC):
    @abstractmethod
    def foo(self):
        raise NotImplementedError()

    @abstractmethod
    def bar(self):
        raise NotImplementedError()


class Parent1(GrandParent):

    def foo(self):
        print("Parent 1")

class Parent2(GrandParent):

    def foo(self):
        print("Parent 2")

class Child1A(Parent1):
    def bar(self):
        print("Child 1A")

class Child1B(Parent1):
    def bar(self):
        print("Child 1B")

这里GrandParent, Parent1Parent2是抽象类,唯一具体的是Child1AChild1B。但是,pylint抱怨Parents :

W0223: Method 'bar' is abstract in class 'GrandParent' but is not overridden (abstract-method)

我可以理解的原因是,通过查看类定义本身,人们无法理解它应该是一个抽象类。我想知道是否需要使用装饰器或其他东西来明确指出这一点?

一种明显的方法是重新定义一个抽象bar方法Parent1Parent2但这对我来说听起来不合理(如果有 10 个其他抽象方法GrandParent需要孩子们覆盖怎么办?,是否应该将所有 10 个都复制粘贴到Parent吗?)


更新

评论中建议这是一种pylint特定行为,尚不支持中间隐式 ABC。要摆脱警告(不禁用它),重新定义使用装饰器的抽象方法GrandParent之一就足够了。确实这解决了问题,但会在多继承场景中导致问题:Parent1@abstractmethod

from abc import ABC, abstractmethod

class Base(ABC):
    @abstractmethod
    def foo(self):
        raise NotImplementedError()

    @abstractmethod
    def bar(self):
        raise NotImplementedError()

    def baz(self):
        return 'baz'

    def qux(self):
        return 'qux'

class C1(Base):

    def qux(self):
        return super().qux().upper()

    # @abstractmethod
    # def bar(self):
    #    raise NotImplementedError()


class C2(Base):
    def foo(self):
        return 'FOO'

    def bar(self):
        return 'BAR'


class D(C1, C2):
    pass

C1是一个中间隐式 ABC,因此pylint发出警告。然而,D是一个具体的类。为了摆脱pylint警告,我们可以取消注释barin的重新定义C1。但是随后D无法实例化 --- Python 抱怨它bar是抽象的,C1而不是在D.

标签: pythonpython-3.xinheritanceabstract-classpylint

解决方案


推荐阅读