The difference between calling method with super and self

Hi forum,

  1. If a method called with super().c(), a method from sibling classes or parents of sibling classes can be called.

  2. If called with self.c(), a method from child class can be called.

  3. And the method of its very own self never gets called by default?

Why is that?

Thanks


  A     B  (Parent Classes) 
  |     |
   \   /
     C      (Child Class)


# code:

import os
import sys
import logging
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from libdir import mylog
mylog.config()

class A:
    def a(self):
        logging.info('')  # line 10
        super().c()
        logging.info('')  # line 12
        self.c()

    def c(self):
        logging.info('')

class B:
    def b(self):
        logging.info('')
        # self.c()

    def c(self):
        logging.info('')  # line 24

class C(A, B):  # (B, A)
    def c(self):
        logging.info('')  # line 28

c = C()
c.a()
print(C.__mro__)


# log:

$ python3 appdir/main.py
2022-03-13 00:09:45,050 INFO /Users/ljh/Documents/helloPy/appdir/main.py:10:a: 
2022-03-13 00:09:45,050 INFO /Users/ljh/Documents/helloPy/appdir/main.py:24:c: 
2022-03-13 00:09:45,050 INFO /Users/ljh/Documents/helloPy/appdir/main.py:12:a: 
2022-03-13 00:09:45,050 INFO /Users/ljh/Documents/helloPy/appdir/main.py:28:c: 
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
$

I come up with new test code.

  1. super refers to sibling or parent method statically.
  2. self refers to class of the instance dynamically.
import os
import sys
import logging
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from libdir import mylog
mylog.config()

class A:
    def f(self):
        logging.info('')

class B(A):
    def f(self):
        logging.info('')

    def f2(self):
        logging.info('self: %s', type(self))
        super().f()  # super refers to sibling or parent method statically.
        self.f()  # self refers to class of the instance dynamically.

class C(B):
    def f(self):
        logging.info('')

B().f2()
logging.info('----')
C().f2()


$ python3 appdir/main.py
main.py:17:f2: self: <class '__main__.B'>
main.py:10:f:
main.py:14:f:
main.py:26:<module>: ----
main.py:17:f2: self: <class '__main__.C'>
main.py:10:f:
main.py:23:f:
$