Python 3 superclass instantiation via derived class’s default constructor

In this code:

class A():
  def __init__(self, x):
    self.x = x
  
  def __str__(self):
    return self.x

class B(A):
  def __str__(self):
    return super().__str__()

b = B("Hi")
print(b)

The output is: Hi.

What is happening under the hood? How does the default constructor in the derived class invoke the super class constructor? How are the params passed to the derived class object get mapped to those of the super class?

1

How does the default constructor in the derived class invoke the super class constructor?

You didn’t override it in B, so you inherited it from A. That’s what inheritance is for.

>>> B.__init__ is A.__init__
True

In the same vein, you may as well not define B.__str__ at all here, since it doesn’t do anything (other than add a useless extra frame into the call stack).

How are the params passed to the derived class object get mapped to those of the super class?

You may be overthinking this. As shown above, B.__init__ and A.__init__ are identical. B.__init__ gets resolved in the namespace of A, since it is not present in the namespace of B.

>>> B.__mro__
(__main__.B, __main__.A, object)
>>> A.__dict__["__init__"]
<function __main__.A.__init__(self, x)>
>>> B.__dict__["__init__"]
...
# KeyError: '__init__'

What is happening under the hood?

Please note that __init__ methods are not constructors. If you’re looking for an analogy of constructors in other programming languages, the __new__ method may be more suitable than __init__. First, an instance of B will created (by __new__), and then this instance will be passed as the first positional argument self to A.__init__, along with the string value “Hi” for the second positional argument x.

3

First, what does it mean to call B in the first place? B is an instance of type, and instances are callable when their classes define __call__. type.__call__ can be thought of as being defined as

def __call__(self, *args, **kwargs):
    obj = self.__new__(self, *args, **kawrgs)
    if isinstance(obj, self):
        obj.__init__(*args, **kwargs)
    return obj

So B("hi") starts as a call to type.__call__(B, "hi").

Inside __call__, we first try to call B.__new__(B, "hi"). Since B.__new__ is not defined, we need to look at B’s method resolution order to find a class that does define __new__.

>>> B.__mro___
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)

A does not, but object does, so we end up with

obj = object.__new__(B, "hi")

which effectively ignores "hi" and returns a “bare” instance of B (the first argument). *

Since obj is indeed an instance of B, isinstance returns True and we call the __init__ method. Once again, obj has no __init__ attribute, so we fall back to the method resolution order of type(obj) to find one, and we find A.__init__. So we execute A.__init__(obj, "hi") before finally returning obj.


* There is a small amount of “magic” that I’m not aware of. object.__new__ can raise a TypeError if it receives arguments that it is not expecting:

>>> object.__new__(object, "hi")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object() takes no arguments

so I’m not sure exactly how object.__new__(B, "hi") works. As far as I can tell, the existence of an __init__ method for the first argument is sufficient to make object.__new__ accept and ignore arbitrary arguments.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Python 3 superclass instantiation via derived class’s default constructor

In this code:

class A():
  def __init__(self, x):
    self.x = x
  
  def __str__(self):
    return self.x

class B(A):
  def __str__(self):
    return super().__str__()

b = B("Hi")
print(b)

The output is: Hi.

What is happening under the hood? How does the default constructor in the derived class invoke the super class constructor? How are the params passed to the derived class object get mapped to those of the super class?

1

How does the default constructor in the derived class invoke the super class constructor?

You didn’t override it in B, so you inherited it from A. That’s what inheritance is for.

>>> B.__init__ is A.__init__
True

In the same vein, you may as well not define B.__str__ at all here, since it doesn’t do anything (other than add a useless extra frame into the call stack).

How are the params passed to the derived class object get mapped to those of the super class?

You may be overthinking this. As shown above, B.__init__ and A.__init__ are identical. B.__init__ gets resolved in the namespace of A, since it is not present in the namespace of B.

>>> B.__mro__
(__main__.B, __main__.A, object)
>>> A.__dict__["__init__"]
<function __main__.A.__init__(self, x)>
>>> B.__dict__["__init__"]
...
# KeyError: '__init__'

What is happening under the hood?

Please note that __init__ methods are not constructors. If you’re looking for an analogy of constructors in other programming languages, the __new__ method may be more suitable than __init__. First, an instance of B will created (by __new__), and then this instance will be passed as the first positional argument self to A.__init__, along with the string value “Hi” for the second positional argument x.

3

First, what does it mean to call B in the first place? B is an instance of type, and instances are callable when their classes define __call__. type.__call__ can be thought of as being defined as

def __call__(self, *args, **kwargs):
    obj = self.__new__(self, *args, **kawrgs)
    if isinstance(obj, self):
        obj.__init__(*args, **kwargs)
    return obj

So B("hi") starts as a call to type.__call__(B, "hi").

Inside __call__, we first try to call B.__new__(B, "hi"). Since B.__new__ is not defined, we need to look at B’s method resolution order to find a class that does define __new__.

>>> B.__mro___
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)

A does not, but object does, so we end up with

obj = object.__new__(B, "hi")

which effectively ignores "hi" and returns a “bare” instance of B (the first argument). *

Since obj is indeed an instance of B, isinstance returns True and we call the __init__ method. Once again, obj has no __init__ attribute, so we fall back to the method resolution order of type(obj) to find one, and we find A.__init__. So we execute A.__init__(obj, "hi") before finally returning obj.


* There is a small amount of “magic” that I’m not aware of. object.__new__ can raise a TypeError if it receives arguments that it is not expecting:

>>> object.__new__(object, "hi")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object() takes no arguments

so I’m not sure exactly how object.__new__(B, "hi") works. As far as I can tell, the existence of an __init__ method for the first argument is sufficient to make object.__new__ accept and ignore arbitrary arguments.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật