Python中子类__init__函数注意项小结

文摘   2023-04-22 11:11   江苏  






01


 引言





许多同学在开始学习Python中的面向对象编程时,对于子类的构造函数的初始化操作,经常会感到些许困惑,这里我来试图让它不那么令人困扰。

闲话少说,我们直接开始吧!





02


 准备工作


在面向对象编程中,为了实现多态,他们经常需要使用继承的思想。对于父类和子类,我们必须非常清楚__init___()函数的作用。

本文重点考虑一下三种情况:首先是父类和子类参数量相同的情况,如下:
# parent & child takes in the SAME number of args
# Animal(name, age) # parent class# Dog(name, age) # child class

接着是子类参数量多于父类的情况,如下:

# child takes in MORE args than parent
# Employee(name, age) # parent class# Executive(name, age, rank) # child class

最后是子类参数量少于父类的情形,如下:

# child takes in FEWER args than parent
# Rectangle(length, width) # parent class# Square(length) # child class




03


 情形一:子类父类参数量一致


我们对上述父类Animal(name, age) 和 子类Dog(name, age)  , 进行简单定义实现。
首先是父类Amimal的定义:
# parent classclass Animal:  def __init__(self, name, age):    self.name = name    self.age = age

接着是子类Dog的定义:

# child classclass Dog(Animal):
# Dog's __init__ should follow Dog(name, age) def __init__(self, name, age):
# super().__init__ here refers to Animal.__init__ super().__init__(name, age)

由于我们的子类Dog继承自父类Animal, 所以当我们运行子类Dog中的__init__函数时:

super()指的是Dog的父类Amimal  

super().__init__()指的是父类Animal中的__init__函数  

当super().__init__()运行时,实质上是Animal中__init__函数在运行,即执行语句self.name=name 以及 self.age=age

由于父类Animal和子类Dog的初始化参数都是(name,age) , 所以我们不需要修改子类Dog__init__函数,我们只需要在子类Dog中简单地使用父类的__init__方法即可。





04


 情形二:子类参数量比父类参数量多


我们对上述父类Employee(name, age)和 子类Executive(name, age, rank), 进行简单定义实现。

首先是父类Employee的定义:
# parent classclass Employee:  def __init__(self, name, age):    self.name = name    self.age = age

接着是子类Executive的定义:

# child classclass Executive(Employee):  # Executive.__init__ follows Executive(name, age, rank)  def __init__(self, name, age, rank):    # super().__init__ refers to Employee.__init__    # super().__init__ should follow Employee(name, age)    super().__init__(name, age)    # super().__init__() does not set rank, so we must do it manually    self.rank = rank

同上,当我们在子类Executive调用super().__init__()时,我们实质上运行的是父类Employee中的 self.name = name self.age = age 。同时由于父类Employee中并没有初始化参数rank , 因此我们需要在子类Executive中手动指定改参数的初始化。

简而言之,我们在子类Executive中调用super().__init__(name, age)self.rank = rank,实质上等价于执行如下语句self.name = name ,self.age = age 以及 self.rank = rank





05


 情形三:子类参数量比父类参数量少


我们对上述父类 Rectangle(length, width) 和子类Square(length) , 进行简单定义实现。

首先是父类 Rectangle 的定义:
# parent classclass Rectangle:  def __init__(self, length, width):    self.length = length    self.width = width

接着是子类Square的定义:

# chid classclass Square(Rectangle):  # Square.__init__ should follow Square(length)  def __init__(self, length):    # super().__init__ should follow Rectangle()    super().__init__(length, length)

我们知道,在子类正方形中默认length=width,所以我们对该类的__init__函数只需要传入一个参数length即可。同样的当我们在子类Square中调用super().__init__()函数时,我们调用的是父类Rectangle中的__init__函数。

通过将参数length传递给子类,并调用父类的初始化函数,实质上(length,length)通过Square传递时,实质上等效于self.length = lengthself.width = length,这和我们的常识正方形中长度和宽度相等是保持一致的。





06


 总结


本文重点介绍了使用Python进行面向对象编程时,父类和子类初始化函数构造时的三种情形下的差异点,可以帮助大家更加深入的理解多态的实现。



嗯嗯,您学废了嘛?







点击上方小卡片关注我






寄语:

我们所听到的一切,都是一个观点,不是事实。

我们所看到的一切,都是一个视角,不是真相。

AI算法之道
一个专注于深度学习、计算机视觉和自动驾驶感知算法的公众号,涵盖视觉CV、神经网络、模式识别等方面,包括相应的硬件和软件配置,以及开源项目等。
 最新文章