2011-01-25 57 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