When I call the base class recursive method from the derived class, the recursive call is done against the derived method, instead of the base class method. How can I avoid that without modifying base class implementation (in example class A)?
Here is an example
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()
I've got this output:
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)
Thanks in advance,
Name mangling is the tool for this job. This would look like this in your case:
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)
Explanation from the linked documentation:
Any identifier of the form
__spam
(at least two leading underscores, at most one trailing underscore) is textually replaced with_classname__spam
, where classname is the current class name with leading underscore(s) stripped.
In your second example, your problem is that the self
you're passing along is an instance of B
, not an instance of A
, so when you attempt to call self.f
you're calling Bf
.
Unfortunately, the behavior you're seeing is really sort of how OO programming should work. Anything you do to work around this is going to be a bit of a hack around the OO paradigm. Another option which might be more explicit than using mangling, but is not necessarily "real recursion", would be to pass along the function you want to recurse on:
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()
This probably isn't the best way this could be written, but I think it gets the idea across. You could alternately try passing Af
in from your call in Bf
.
If you can't modify A
's implementation, you can take advantage of the difference in function signatures.
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)
I would suggest renaming the base classes f
method to a private method called _f
and having that recurse. You can then introduce a new f
method to the base class which just calls _f
. Then your free to change f
in the subclass.
However it may not be considered good practice to change the method signature in a subclass.
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()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.