2017-10-18 59 views
1

對不起,我想不出一個更好的方式來標題!「傳遞」一個抽象方法的實現通過在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 

是否有一個「正確」的方法是什麼?我找不到答案。

回答

0

「正確」方式是,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() 
0

你不應該定義一個抽象基如果你是立即將不執行該方法的抽象方法類。最好的辦法是定義沒有抽象方法的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'] 
0

當然,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 

這聽起來像是你在找什麼?

0

儘管可能會違背某些人的風格來擁有抽象類的繼承層次結構,但我認爲您當前的代碼很好。如果你不想要,你不需要改變任何東西。

Pylint給你一個警告,因爲你正在做某些事情,在某些情況下可能是錯誤的,但在其他情況下可能是OK的。如果您希望B成爲一個具體類,則從A繼承抽象方法而不會覆蓋它將會是一個問題。但是如果你期望BA一樣是抽象的,那麼它會發現它不覆蓋它繼承的抽象方法。

因此,您可以忽略來自Pylint的警告,或者通過在文件中添加註釋# pylint: disable=W0223來取消警告。具體取決於放置評論的位置,我相信它可以禁用僅針對特定類或整個模塊的警告。