Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a sibling class in Python?

Python 2 documentation says that super() function "returns a proxy object that delegates method calls to a parent or sibling class of type."

The questions:

  1. What is a sibling class in Python?
  2. How do you delegate a method call to a sibling class?

My presumption was that a sibling for a given class is a class that inherits from the same parent. I drafted the following code to see how a method call can be delegated to a sibling, but it didn't work. What do I do or understand wrong?

class ClassA(object):
    def MethodA(self):
        print "MethodA of ClassA"

class ClassB(ClassA):
    def MethodB(self):
        print "MethodB of ClassB"

class ClassC(ClassA):
    def MethodA(self):
        super(ClassC, self).MethodA()

    def MethodB(self):
        super(ClassC, self).MethodB()

if __name__ == '__main__':
    ClassC().MethodA() # Works as expected

    # Fail while trying to delegate method to a sibling.
    ClassC().MethodB() # AttirbuteError: 'super' object has no attribute 'MethodB'
like image 313
golem Avatar asked Jan 14 '15 23:01

golem


People also ask

What is a sibling class?

The Big Brother / Big Sister Class helps prepare siblings for the arrival of a new baby. Participants will learn to understand the changes that are about to occur in their family and how to properly handle the new baby. Siblings will be taught about babies and how they can be involved.

What is super () __ Init__?

__init__() Call in Python. When you initialize a child class in Python, you can call the super(). __init__() method. This initializes the parent class object into the child class. In addition to this, you can add child-specific information to the child object as well.

What is parent class and child class in Python?

Parent class is the class being inherited from, also called base class. Child class is the class that inherits from another class, also called derived class.

What is __ new __ in Python?

The __new__() is a static method of the object class. It has the following signature: object.__new__(class, *args, **kwargs) Code language: Python (python) The first argument of the __new__ method is the class of the new object that you want to create.


2 Answers

After some further research and reading Python’s super() considered super! article I came to the following conclusions:

  1. A sibling class is what I was thinking it was. It is a class that inherits from the same parent. It is the definition of the Python documentation that threw me off the course. It seems that when Python documentation says delegates method calls to a parent or sibling class it means to a parent or parent's sibling which is also a base class of a given child. That is a diamond inheritance must take place.

  2. super() function delegates a method call to a parent's sibling class automatically based on MRO (method resolution order).

Here's an interesting case I found while experimenting with super() function:

class Class0(object):
    def MethodA(self):
        print("MethodA of Class0")

class ClassA(Class0):
    def MethodA(self):
        super(ClassA, self).MethodA()
        print("MethodA of ClassA")

class ClassB(Class0):
    def MethodA(self):
        print("MethodA of ClassB")

class ClassC(ClassA, ClassB):
    def MethodA(self):
        super(ClassC, self).MethodA()

if __name__ == '__main__':
    ClassC().MethodA()

The code will print

MethodA of ClassB
MethodA of ClassA

If you as me wonder why MethodA of Class0 never gets printed, here is the explanation as I understand it. The MRO of the ClassC as printed with print(ClassC.__mro__) is

(<class '__main__.ClassC'>, <class '__main__.ClassA'>, <class '__main__.ClassB'>, <class '__main__.Class0'>, <class 'object'>).

Now if you follow the MRO the super() function of MethodA() of ClassC will call the MethodA() of ClassA, which before printing will call MethodA() of classB (since it's next in MRO). And the MethodA() of ClassB in its turn will just print and exit since it doesn't use super() function to delegate the method call further up the MRO chain.

like image 150
golem Avatar answered Sep 28 '22 01:09

golem


A sibling is a class with the same parent, as you suspected. The case you're missing is that super could call a sibling method if this class itself is being multiply inherited from:

class A(object):
  def something(self):
    print("A")
class B(A):
  def something(self):
    print("B")
class C(A):
  def something(self):
    print("C, about to call super()")
    super(C, self).something()
class D(C, B):
  def something(self):
    super(D, self).something()

>>> D().something()
C, about to call super()
B

In C, we called super(), but we got B - which is a sibling, not a parent and not the parent of a sibling, but an actual direct sibling of C.

like image 38
lmm Avatar answered Sep 28 '22 02:09

lmm