“传递”一个抽象方法的实现通过在Python中进一步下去?

问题描述:

对不起,我想不出一个更好的方式来标题!“传递”一个抽象方法的实现通过在Python中进一步下去?

基本上,我想一个抽象基类,则一个子类的一个不起实现抽象方法,则一个子类的,其实现该方法。这也可能是用一个例子更容易:

import abc 
class A(abc.ABC): 
    def __init__(self, some_var): 
    self.some_var = some_var 

    @abc.abstractmethod 
    def some_method(self): 
    pass 

class B(A): 
    def some_b_method(self): 
    print("Hello") 

class C(B): 
    def some_method(self): 
    self.some_b_method() 
    print(self.some_var) 

c = C('world') 
c.some_method() 

这是我怎么会想到它的工作,但对于级以上pylint的报告warning 0223

pylint的不给我任何问题,如果我修改类包括以下内容,但重复代码似乎是错误的:

@abc.abstractmethod 
def some_method(self): 
    pass 

是否有一个“正确”的方法是什么?我找不到答案。

“正确”方式是,class B不从abstract class A继承;如果这样做,B必须实现的A

另一种方法都abstract methods它有来自class Aclass C继承和class B,具有独立的AB

import abc 
class A(abc.ABC): 
    def __init__(self, some_var): 
    self.some_var = some_var 

    @abc.abstractmethod 
    def some_method(self): 
    pass 

class B(): 
    def some_b_method(self): 
    print("Hello") 

class C(A, B): 
    def some_method(self): 
    self.some_b_method() 
    print(self.some_var) 

c = C('world') 
c.some_method() 

你不应该定义一个抽象基如果你是立即将不执行该方法的抽象方法类。最好的办法是定义没有抽象方法的ABC,并且定义一个包含该方法的mixin类。您可以从class A子类class B,然后子类class Cclass B和mixin。

import abc 
class A(abc.ABC): 
    def __init__(self, some_var): 
     self.some_var = some_var 

class MixinA(abc.ABC): 
    @abc.abstractmethod 
    def some_method(self): 
     pass 

class B(A): 
    def some_b_method(self): 
     print("Hello") 

class C(B, MixinA): 
    def some_method(self): 
     self.some_b_method() 
     print(self.some_var) 

c = C('world') 
c.some_method() 

# returns: 
Hello 
world 

# list the methods: 
[m for m in dir(c) if not m.startswith('_')] 
# returns: 
['some_b_method', 'some_method', 'some_var'] 

当然,Python可以这样做:只需在中间类的方法定义中提升NotImplementedError即可。

class BaseClass : 

    def method(...) : 
     ... actually do something ... 
    #end method 

#end BaseClass 

class Subclass(BaseClass) : 

    def method(...) : 
     raise NotImplementedError 
    #end method 

    ... 

#end Subclass 

class SubSubclass(Subclass) : 

    def method(...) : 
     ... actually do something else ... 
    #end method 

#end SubSubclass 

这听起来像是你在找什么?

尽管可能会违背某些人的风格来拥有抽象类的继承层次结构,但我认为您当前的代码很好。如果你不想要,你不需要改变任何东西。

Pylint给你一个警告,因为你正在做某些事情,在某些情况下可能是错误的,但在其他情况下可能是OK的。如果您希望B成为一个具体类,则从A继承抽象方法而不会覆盖它将会是一个问题。但是如果你期望BA一样是抽象的,那么它会发现它不覆盖它继承的抽象方法。

因此,您可以忽略来自Pylint的警告,或者通过在文件中添加注释# pylint: disable=W0223来取消警告。具体取决于放置评论的位置,我相信它可以禁用仅针对特定类或整个模块的警告。