简体   繁体   中英

Python: RecursionError with Class Inheritance

I have given a class A with methods f and g . In the implementation of Af , the method self.g is called, ie Ag is used. (I am not able/willing to change this class A since it comes from a python package.)

Now I want to build a child class B of A and want to overwrite the methods f and g . In the implementation of Bf , I call super().f , ie Af is used. In the implementation of Bg , I call self.f , ie Bf is used.

I would expect that everything is well defined: Bg calls Bf calls Af calls Ag

In fact, I get a RecursionError as I am running into an infinite number of recursions: Bg calls Bf calls Af calls Bg

What do I not understand correctly?

Here is a implementation:

class A:
    def f(self):
        print('Method A.f was called.')
        self.g()

    def g(self):
        print('Method A.g was called.')

class B(A):
    def f(self):
        print('Method B.f was called.')
        super().f()

    def g(self):
        print('Method B.g was called.')
        self.f()

b = B()
b.g()

For clarification: In my application, A is a scikit-learn class, f is fit and g is fit_transform . In this scikit-learn class, fit_transform is explicitly overwritten, and fit unfortunately uses fit_transform . To ensure that my child class B does not inherit fit_transform from A , I have to redefine it in the usual way, and this leads to infinite recursion as explained.

The g method of B overwrites the one of A as you said, meaning Af will call Bg, if you change the name of the method Bg your code will run as you expect it to

What do I not understand correctly?

Even though self.g() was called within Af , the value that was passed as self is still an instance of B , so Bg is looked up by this operation rather than Ag .

It would help if you could explain what problem you are trying to solve with this structure. In particular, I don't understand why, for any real-world code, it would be useful within the B class for g to call upon f , but in the base class to do it the other way around.

self is bound to the B object on which .g() was called.

Try replacing the inheritance with composition instead:

class A:
    def f(self):
        print('Method A.f was called.')
        self.g()

    def g(self):
        print('Method A.g was called.')

class B:
    def __init__(self, a):
        self.a = a

    def f(self):
        print('Method B.f was called.')
        self.a.f()

    def g(self):
        print('Method B.g was called.')
        self.f()

a = A()
b = B(a)
b.g()

Output:

Method B.g was called.
Method B.f was called.
Method A.f was called.
Method A.g was called.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM