2011-10-22 233 views
10

此代码抛出一个异常,AttributeError,“wtf!”,因为A.foo()正在调用B.foo1(),是不是应该拨打A.foo1()?我怎样才能迫使它调用A.foo1()(和内A.foo()任何方法调用应该调用A.*调用覆盖方法,超类调用覆盖方法

class A(object): 
    def foo(self): 
     print self.foo1() 

    def foo1(self): 
     return "foo" 

class B(A): 
    def foo1(self): 
     raise AttributeError, "wtf!" 

    def foo(self): 
     raise AttributeError, "wtf!" 

    def foo2(self): 
     super(B, self).foo() 

myB = B() 
myB.foo2() 
+1

你基本上要求Python抛弃动态性和虚拟方法,并*以某种方式*根据函数的词法定义跳过部分属性查找链。不会发生。 – delnan

回答

5

它是否按预期运行,作为世界编程语言工作的100%。子类重写父类的所有方法。

但是,如果你真的很想打电话给A.foo1(),你可以这样做(我不能保证)。在任何情况下,你都不能这样做,因为这违反了所有良好编程原则。

class A(object): 

    def foo(self): 
     A.foo1(self) 
2

在代码:

def foo2(self): 
    super(B, self).foo() 

自我是B.

的实例。当从A衍生的方法是通过B的一个实例,将开始寻找在从命名空间称为B,并且只有在找不到该方法时(例如,不被B覆盖),使用来自A的实现,但始终自我参考B.在任何情况下,self都是A的实例。

6

In A类,而不是调用self方法,您需要调用A方法并手动传入self

这不是正常的做事方式 - 你应该有一个真的这样做的好理由。

class A(object): 
    def foo(self): 
     print A.foo1(self) 

    def foo1(self): 
     return "foo" 

class B(A): 
    def foo1(self): 
     raise AttributeError, "wtf!" 

    def foo(self): 
     raise AttributeError, "wtf!" 

    def foo2(self): 
     super(B, self).foo() 

myB = B() 
myB.foo2() 
-1

可以看到Python在这里做了什么,但重写的方式有点极端。当A类定义了100个属性并且B类继承了这些属性并添加了另外1个属性的情况下。我们希望能够让B的__init __()调用A的__init __(),并让B的代码只定义它的单个属性。同样,如果我们在A中定义一个reset()方法来将所有属性设置为零,那么B的相应reset()方法应该能够调用A的reset()方法,然后将单个B属性替换为零不得不复制A的所有代码。 Python正在变得困难,这应该是面向对象编程的主要优势;也就是代码的重用。这里最好的选择是避免重写我们真正想要重用的方法。如果你想在这里得到与Python并发症的感觉,试试这个代码:

class X(object): 
    def __init__ (self): 
     print "X" 
     self.x = 'x' 
     self.reset() 
     print "back to X" 
    def reset (self): 
     print "reset X" 
     self.xx = 'xx' 

class Y(X): 
    def __init__ (self): 
     print "Y" 
     super(Y,self).__init__() 
     self.y = 'y' 
     self.reset() 
     print "back to Y" 
    def reset (self): 
     print "reset Y" 
     super(Y,self).reset() 
     print "back to reset Y" 
     self.yy = 'yy' 

aY = Y() 

(为了使这项工作正常,消除__init __()类Y的self.reset()调用)