覆盖python中的递归方法

时间:2011-07-27 15:18:31

标签: python inheritance recursion override

当我从派生类调用基类递归方法时,递归调用是针对派生方法而不是基类方法完成的。如何避免而不修改基类实现(在示例类A中)?

这是一个例子

class A(object):
    # recursive method
    def f(self, x):
        print x,
        if x < 0:
            self.f(x+1)
        if x > 0:
            self.f(x-1)
        if x == 0:
           print ""

class B(A):
   # Override method 
   def f(self):
       # do some pretty cool stuff
       super(B, self).f(25)

if __name__ == "__main__":
    A().f(5)
    B().f()

我有这个输出:

5 4 3 2 1 0 
25
Traceback (most recent call last):
  File "./test.py", line 19, in <module>
     B().f()
  File "./test.py", line 15, in f
     super(B, self).f(25)
   File "./test.py", line 9, in f
     self.f(x-1)
  TypeError: f() takes exactly 1 argument (2 given)

提前致谢,

4 个答案:

答案 0 :(得分:4)

Name mangling是这项工作的工具。在你的情况下,这看起来像这样:

class A(object):
    # recursive method
    def f(self, x):
        print x,
        if x < 0:
            self.__f(x+1)
        if x > 0:
            self.__f(x-1)
        if x == 0:
           print ""

    __f = f

class B(A):
   # Override method 
   def f(self):
       # do some pretty cool stuff
       super(B, self).f(25)

链接文档的说明:

  

__spam形式的任何标识符(至少两个主要下划线,   最多一个尾随下划线)在文本上被替换为   _classname__spam,其中classname是当前的类名   剥离前导下划线。

答案 1 :(得分:1)

在您的第二个示例中,您的问题是您传递的selfB的实例,而不是A的实例,因此当您尝试调用{ {1}}您正在呼叫self.f

不幸的是,您所看到的行为实际上是OO编程应该的工作方式。你为解决这个问题所做的任何事情都会对OO范式产生一些影响。另一个可能比使用修改更明确的选项,但不一定是“真正的递归”,将传递你想要递归的函数:

B.f

这可能不是写这篇文章的最佳方式,但我认为它可以解决这个问题。您也可以尝试通过class A(object): # recursive method def f(self, x, func=None): if func is None: func = A.f print x, if x < 0: func(self,x+1,func) if x > 0: func(self,x-1,func) if x == 0: print "" class B(A): # Override method def f(self): # do some pretty cool stuff super(B, self).f(25) if __name__ == "__main__": A().f(5) B().f() 中的A.f传递B.f。{/ p>

答案 2 :(得分:1)

如果你无法修改A的实现,你可以利用功能签名的不同。

class B(A):
    def f(self, x=None):
        if x is None:
            # do some pretty cool stuff
            self.f(25)
        else:
            super(B, self).f(x)

答案 3 :(得分:0)

我建议将基类f方法重命名为名为_f的私有方法并进行递归。然后,您可以向只调用f的基类引入新的_f方法。然后您可以自由更改子类中的f

但是,在子类中更改方法签名可能不是一种好的做法。

class A(object):
    def f(self, x):
        return self._f(x)

    # recursive method
    def _f(self, x):
        print x,
        if x < 0:
            self._f(x+1)
        if x > 0:
            self._f(x-1)
        if x == 0:
           print ""

class B(A):
   # Override method 
   def f(self):
       # do some pretty cool stuff
       super(B, self).f(25)

if __name__ == "__main__":
    A().f(5)
    B().f()