2011-01-25 55 views
5

Abstract base classes can still be handy in Python.在寫一個抽象基類,我想每個子類中有,比方說,一個spam()方法,我想寫的東西是這樣的:Python的超(),抽象基類,NotImplementedError

class Abstract(object): 
    def spam(self): 
     raise NotImplementedError 

挑戰還包括想要使用super(),並通過將其包含在整個子類鏈中來正確執行。在這種情況下,看來我必須包裝每super調用類似如下:

class Useful(Abstract): 
    def spam(self): 
     try: 
      super(Useful, self).spam() 
     except NotImplementedError, e: 
      pass 
     print("It's okay.") 

沒關係了一個簡單的子類,但寫有許多方法的類時,在try-除了事情變得有點麻煩,而且有點醜陋。是否有更優雅的從抽象基類繼承的方法?我只是做錯了嗎?

+5

這使得很少的感覺。你應該知道哪些超類方法被實現了(爲什麼`super`有意義),哪些沒有實現,因爲它們是抽象的。你可以閱讀來源。 – 2011-01-25 22:09:27

+0

`raise SyntaxError`也在語言中。問題是「爲什麼在抽象類的簡單檢查可以節省編寫所有代碼時編寫所有代碼」? – 2011-01-25 22:15:58

+0

@ S.洛特啊,現在明白了。順便說一句,你應該提交這個答案,因爲它是。 – gotgenes 2011-01-25 22:16:44

回答

8

您可以在Python 2.6+與abc module乾淨做到這一點:

import abc 
class B(object): 
    __metaclass__ = abc.ABCMeta 
    @abc.abstractmethod 
    def foo(self): 
     print 'In B' 

class C(B): 
    def foo(self): 
     super(C, self).foo() 
     print 'In C' 

C().foo() 

輸出將是

In B 
In C 
7

不要寫所有的代碼。抽象類的簡單檢查可以節省您編寫所有代碼的時間。

如果該方法是抽象的,則具體子類不會調用super。

如果方法是具體的,具體子類確實調用super。

3

瞭解這一點的關鍵是super()是用於實現協同繼承。班級如何合作取決於程序員。 super()是不是魔術,並不知道你想要什麼!對於不需要協作繼承的扁平層次結構使用super並沒有多大意義,所以在這種情況下,S. Lott的建議就顯現出來了。有用的5子類或可能不希望使用super()根據自己的目標:)

例如:摘要答:< - B,但你要支持C的插入,就像這樣< - Visual C < - B 。

class A(object):                       
    """I am an abstract abstraction :)""" 
    def foo(self): 
     raise NotImplementedError('I need to be implemented!') 

class B(A): 
    """I want to implement A""" 
    def foo(self): 
     print('B: foo') 
     # MRO Stops here, unless super is not A 
     position = self.__class__.__mro__.index 
     if not position(B) + 1 == position(A): 
      super().foo() 

b = B()  
b.foo() 

class C(A): 
    """I want to modify B and all its siblings (see below)""" 
    def foo(self): 
     print('C: foo') 
     # MRO Stops here, unless super is not A 
     position = self.__class__.__mro__.index 
     if not position(C) + 1 == position(A): 
      super().foo() 

print('') 
print('B: Old __base__ and __mro__:\n') 
print('Base:', B.__bases__) 
print('MRO:', B.__mro__) 
print('') 
# __mro__ change implementation 
B.__bases__ = (C,) 
print('B: New __base__ and __mro__:\n') 
print('Base:', B.__bases__) 
print('MRO:', B.__mro__) 
print('') 
b.foo() 

和輸出:

B: foo 

B: Old __base__ and __mro__: 

Base: (<class '__main__.A'>,) 
MRO: (<class '__main__.B'>, <class '__main__.A'>, <class 'object'>) 

B: New __base__ and __mro__: 

Base: (<class '__main__.C'>,) 
MRO: (<class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) 

B: foo 
C: foo