0
class Z():
    def func():
        print ("I'm in Z")
class A(Z):
    def func():
        print ("I'm in A")
class B(Z):
    def func():
        print ("I'm in B")

class C(A,B):
    pass
    #def func():
     #   print ("I'm in C")

ob1 = C

print ("Calling function func ")
ob1.func()

Output is:

Calling function func
I'm in A

But according to the How does Python's super() work with multiple inheritance?

Order should be "depth-first left-to-right traversal" + "removing duplicates expect for the last"

As explained by /visionscaper (user:889617),

Why is this difference ?

Ry-
  • 218,210
  • 55
  • 464
  • 476
girishlc
  • 9
  • 3
  • 2
    It's doing exactly depth first left to right. A is left of B as a parent of C. What's tripping you up? – Mad Physicist Dec 30 '17 at 03:37
  • 3
    Starting at C, the next base in the depth-first left-to-right traversal is the leftmost base class of C: A. What did you expect? – Ry- Dec 30 '17 at 03:37
  • Lookup order here would be A, Z, B (A, Z from B hierarchy removed as duplicates.) – Mad Physicist Dec 30 '17 at 03:40
  • I'm going to go ahead and vote to close as unclear. – Mad Physicist Dec 30 '17 at 03:41
  • @MadPhysicist: Your order is incorrect. `B` must occur before `Z` in the MRO. – Blckknght Dec 30 '17 at 05:48
  • @Blkknght. Not if the order is depth first. – Mad Physicist Dec 30 '17 at 13:01
  • @MadPhysicist: When you remove duplicates, you remove the earlier ones, rather than the later ones. This question has a typo: "expect for the last" is supposed to say "except for the last". The answer it came from (which I linked from my answer below) has the rule written correctly. – Blckknght Dec 30 '17 at 22:09

2 Answers2

2

A depth-first left-to-right traversal of the inheritance hierarchy C would give you: [C, A, Z, B, Z]. Since Python doesn't allow duplicates, the first Z is removed, and you end up with [C, A, B, Z]. Thus, when you call C.func(), you get the implementation from A. There are no super calls in A.func, so that's the end of the line.

You can get the full MRO for any class by calling its mro method:

>>> C.mro()
[__main__.C, __main__.A, __main__.B, __main__.Z, object]

In the answer I think you were referring to, each __init__ method called the next one in the MRO by using super. But since they each make their super call before printing their own message, the order of the printed lines ends up being the reverse of the order the functions are called in. You could get it to work in the same order as the MRO by swapping the print lines with the super calls so that the print calls happen first.

Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • Hi Blckknght,Thanks for clearing the doubts. Actually I got confuse when I used super functionality in the above example. And thread which you referred was correct, " the answer I think you were referring to" – girishlc Jan 02 '18 at 09:32
  • thanks others too, who attempted to clear my doubts. – girishlc Jan 02 '18 at 09:33
-1

When talking about the traversal, it searches depth first, from left to right, until it finds it. It calls the first one it finds. In your case:

  1. It searches for func in C - doesn't find it. Goes down to the left.
  2. It searches for func in A - finds it. Done. Prints I'm in A.

Where this is important is if A didn't override func. In this case:

  1. It searches for func in C - doesn't find it. Goes down to the left.
  2. It searches for func in A - doesn't find it. Goes down, not right.
  3. It searches for func in Z - finds it there. Prints I'm in Z.
SCB
  • 5,821
  • 1
  • 34
  • 43
  • May as well finish: jumps right to B, skips A, Z as duplicates. Checks the instance dictionary. Raises an attribute error. – Mad Physicist Dec 30 '17 at 03:43
  • Your second scenario is completely wrong. If `A` didn't implement `func`, then `B`'s version would be called. The MRO for `C` is `C, A, B, Z`. `Z` will never appear before `B` in any MRO since it's it is `B`'s parent. – Blckknght Dec 30 '17 at 05:46
  • Ah yes, I see, you are correct. This is what I get for not testing what I write. – SCB Dec 31 '17 at 00:44