Should subclass always invoke superclass' init function?

Python is an Object Oriented programming language. Inheriting is such a common case, and mostly we will invoke the superclass' init function just in the subclass' init function. Bu

Python is an Object Oriented programming language. Inheriting is such a common case, and mostly we will invoke the superclass’ init function just in the subclass’ init function.

python
#!/usr/bin/python
class Base:
	def __init__(self, name = "Lucy"):
		self.name = name
		
	def say(self):
		print(f"{self.__class__} said: Hello!")

class Child(Base):
	def __init__(self, color):
		super().__init__()
		self.color = color

But is the super().init() a must? What if we Comment out the second last line.

python
class Child(Base):
	def __init__(self, color):
		# super().__init__()
		self.color = color

and then run a test:

python
# new superclass
base = Base("Lisa")
print(base.name)
base.say()

# new subclass
child = Child("blue")
try:
        # try to get superclass' attribute: name
	print(child.name)
	print(child.color)
except Exception as e:
	print(e)

# invoke an inheited method: say
child.say()

We got output like this:

python
Lisa
<class '__main__.Base'> said: Hello!
'Child' object has no attribute 'name'
<class '__main__.Child'> said: Hello!

The subclass still inherited all methods of the superclass, but the attribute ’name’ has gone.

Why?

Python is different from other OOP languages such as C++ or Java, etc. The subclass constructure does not depend on its’ superclass. Let’s make some changes to see what happend in the init function.

text
#!/usr/bin/python
class Base:
	def __init__(self, name = "Lucy"):
		print(f"befor __init__, {self.__class__}:")
		print(dir(self))
		self.name = name
		print(f"after __init__, {self.__class__}:")
		print(dir(self))
		
	def say(self):
		print(f"{self.__class__} said: Hello!")
		

class Child(Base):
	def __init__(self, color):
		print(f"befor __init__, {self.__class__}:")
		print(dir(self))
		# super().__init__()
		self.color = color
		print(f"after __init__, {self.__class__}:")
		print(dir(self))

Then run the same test code, we got a long output, this is a part of it:

python
befor __init__, <class '__main__.Child'>:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'say']
after __init__, <class '__main__.Child'>:
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'color', 'say']

As we can see, before the init function invoked, sublass has already inherited the method “say” and the attribute “name” is added to the subclass right during the init function.

That means if the logic in superclass‘ init function is not necessary it can be just ignored.

— EOF —
版权归作者所有,如需转载,请保留版权声明。
给作者发送 email: [email protected]