5

Someone had this exact same problem on this site, but the answer didn't relate to the part I have trouble with.
Inheritance - Method Calls

Consider the following class definitions.

class C1(object):
 def f(self):
 return 2*self.g()
 def g(self):
 return 2
class C2(C1):
 def f(self):
 return 3*self.g()
class C3(C1):
 def g(self):
 return 5
class C4(C3):
 def f(self):
 return 7*self.g()
obj1 = C1()
obj2 = C2()
obj3 = C3()
obj4 = C4()

For this problem you are to consider which methods are called when the f method is called. So for example, when obj1.f() is called, the f method of C1 is called which calls the g method of C1. This could be represented as a 'calling list' of the form

['C1.f', 'C1.g'] 

Write three assignment statements that, respectively, assigns the 'calling list' for obj2.f() to the variable obj2_calls, assigns the 'calling list' for obj3.f() to the variable obj3_calls and assigns the 'calling list' for obj4.f() to the variable obj4_calls.

I have no problem understanding the first assignment, it is obj2_calls = ['C2.f', 'C1.g']
but I am wracking my brain trying to figure out the next one. I thought since there is no C3.f that the list would be ['C1.f'] but unfortunately it's not.

Just to clear up, this IS homework

timss
10.3k4 gold badges37 silver badges56 bronze badges
asked Apr 22, 2013 at 1:15
5
  • 3
    Add some print statements to each function to figure out what's really going on. Commented Apr 22, 2013 at 1:19
  • if you type in C3.f you'll see c3.f <unbound method C3.f> which means its a part of the class C3 Commented Apr 22, 2013 at 1:25
  • Hi guys very helpful, using print I have the correct answer. But I used more common sense to get that than understanding of the code. I'd still like to understand why the answer was obj3_calls = ['C1.f', 'C3.g'] . I don't get why 'c3.g' is called after 'c1.f' Commented Apr 22, 2013 at 1:31
  • Just to be certain I'm understanding the assignment correctly the proper answer is ['C1.f', 'C3.g'], correct? Commented Apr 22, 2013 at 1:33
  • Yep, that's what I got Commented Apr 22, 2013 at 1:33

2 Answers 2

3

This has to do with the method resolution order (MRO) of your class. (see here for some useful info)

As you stated correctly, there is no C3.f function, so python looks up the f method on the first base-class in the MRO that has f defined. In this case, that is (C1). Now, that method (C1.f) calls self.g(). In this case self is an instance of C3, so of course, self.g calls C3.g since that is the highest g function in the MRO. If you wanted to guarantee that you get C1.g, you'd need to do it explicitly:

class C1(object):
 def f(self):
 return 2*C1.g(self)
 def g(self):
 return 5

which also makes a nice lead-in to talking about double-underscore name mangling. Since that is a separate topic though, maybe it's best to only leave a link to some useful documentation.

answered Apr 22, 2013 at 1:35
Sign up to request clarification or add additional context in comments.

1 Comment

Awesome, thanks for that, and to everyone for their help. I understand now
1

obj3_calls is ['C1.f', 'C3.g']. As you point out, there is no C3.f in that class, but this method is inherited from C1. This one in turn calls self.g, and since C3.g is defined, it overrides the method that is inherited from C1.

answered Apr 22, 2013 at 1:34

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.