您的“关注”和“点赞”,是信任,是认可,是支持,是动力…
如意见相佐,可留言。
本人必将竭尽全力试图做到准确和全面,终其一生进行修改补充更新。
文章目录
面向对象编程语言三大特性,如下所示,
- 封装:请参见博文《Python 封装详解》。
- 继承:请参见本文。
- 多态:请参见博文《Python 多态详解》。
1 继承概述
继承(inheritance)是面向对象软件技术当中的一个概念。这种技术使得重复使用以前的代码非常容易,能够大大缩短开发周期,降低开发成本。
继承机制就是指子类继承父类的特征和行为,使得子类对象(实例)具有父类的属性和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
在 Python 中,实现继承的类称为子类或派生类,被继承的类称为父类、基类或超类。
使用语法格式如下所示:
class 类名(父类1, 父类2, ...):
# 类定义部分
对以上格式说明,
- 子类继承父类时,只需在定义子类时,将父类(可以是多个)放在子类之后的圆括号里即可。
- 注意一:如果该类没有显式指定继承自哪个类,则默认继承 object 类,object 类是 Python 中所有类的父类。
- 注意二:Python 的继承是多继承机制,一个子类可以同时拥有多个直接父类。
- 注意三:使用多继承经常需要面临多个父类中包含同名的类属性或类方法这样的问题。Python 是根据子类继承多个父类时这些父类的前后次序来处理的,即排在前面父类中的类属性或类方法会覆盖排在后面父类中的同名类属性或类方法。
- 注意四:虽然 Python 在语法上支持多继承,但不建议大家使用多继承。因为多继承和单继承相比的话,多继承容易让代码逻辑复杂、思路混乱。
举例如下所示:
例一,多继承
class People:
def eat(self):
print('吃的行为。')
class Animal:
def sleep(self):
print('睡的行为。')
# 定义一个 Person 子类,同时继承 People 类和 Annimal 类
class Person(People, Animal):
pass # 不定义类体内容
person = Person() # 创建子类 Person 的对象
person.eat()
person.sleep()
运行结果:
吃的行为。
睡的行为。
例二,多个父类中包含同名的类属性或类方法
class People:
name = '阿杰'
def eat(self):
print('People 父类:eat() 方法。')
def sleep(self):
print('People 父类:sleep() 方法。')
class Animal:
name = '码农阿杰'
def eat(self):
print('Animal 父类:eat() 方法。')
def sleep(self):
print('Animal 父类:sleep() 方法。')
# 定义一个 Person 子类,同时继承 People 类和 Annimal 类
class Person(People, Animal):
pass # 不定义类体内容
person = Person() # 创建子类 Person 的对象
print(person.name) # 调用父类们中的同名属性
# 调用父类们中的同名方法
person.eat()
person.sleep()
运行结果:
阿杰
People 父类:eat() 方法。
People 父类:sleep() 方法。
2 重写:重写父类方法
2.1 重写概述
子类继承了父类,那么子类就拥有了父类所有的类属性和类方法。
如果子类有新的需求,可以扩展一些属性和方法,甚至可以重写父类的方法。
重写(Override)指的是子类重新编写了一个和父类相同名字的方法。那么子类的这个方法将覆盖父类中同名的方法。
举例如下所示:
class People:
def eat(self):
print('People 父类:eat() 方法。')
def sleep(self):
print('Animal 父类:sleep() 方法。')
# 定义一个 Person 子类,继承 People 类
class Person(People):
def eat(self):
print('Person 子类:eat() 方法。')
person = Person() # 创建子类 Person 的对象
person.eat()
运行结果:
Person 子类:eat() 方法。
2.2 调用父类中被重写的方法
如果想调用父类中被重写的方法,使用类名调用其类方法即可。
注意:Python 不会为该方法的第一个 self
参数自定绑定值,因此采用这种调用方法,需要手动为 self 参数传参(即传入调用者实例对象)。
举例如下所示:
class People:
def eat(self):
print('People 父类:eat() 方法。')
def sleep(self):
print('Animal 父类:sleep() 方法。')
# 定义一个 Person 子类,继承 People 类
class Person(People):
def eat(self):
print('Person 子类:eat() 方法。')
person = Person() # 创建子类 Person 的对象
People.eat(person) # 调用父类被重写的方法
运行结果:
People 父类:eat() 方法。
3 super() 函数:调用父类构造方法
3.1 调用父类构造方法概述
父类的构造方法可以被子类继承,也可以重写。
注意一:Python 支持多继承,如果子类继承了多个父类,那么子类对象在调用父类们的构造方法时,会优先选择排在最前面的父类中的构造方法。
注意二:如果子类中没有重写父类的构造方法,父类中的构造方法会自动被调用;如果在子类中重写了父类的构造方法,父类的构造方法不会被自动调用,必须在子类的构造方法中手动调用父类的构造方法。
3.2 调用父类构造方法的方式
(1)“非绑定”方式
Python 中允许使用类名直接调用实例方法(构造方法也是实例方法),但必须手动为该实例方法的第一个 self 参数传递参数,这种调用方法的方式被称为“非绑定”方式。
在多继承中,此种方式可以调用指定父类的构造方法。
举例如下所示:
例一,子类中不定义构造方法(即不重写父类的构造方法),父类的构造方法会被自动调用
class People:
def __init__(self):
print('People 父类中的构造方法。')
class Animal:
def __init__(self):
print('Animal 父类中的构造方法。')
# 定义一个 Person 子类,继承 People 类和 Animal 类
class Person(People, Animal):
def say(self):
print('子类中的 say() 方法。')
person = Person() # 实例化子类
person.say()
运行结果:
People 父类中的构造方法。
子类中的 say() 方法。
例二,子类中定义了构造方法,如果想调用父类的构造方法,必须手动调用
class People:
def __init__(self):
print('People 父类中的构造方法。')
class Animal:
def __init__(self):
print('Animal 父类中的构造方法。')
# 定义一个 Person 子类,继承 People 类和 Animal 类
class Person(People, Animal):
def __init__(self):
Animal.__init__(self) # 调用 Animal 父类的构造方法
People.__init__(self) # 调用 People 父类的构造方法
print('Person 子类中的构造方法。')
person = Person() # 实例化子类
运行结果:
Animal 父类中的构造方法。
People 父类中的构造方法。
Person 子类中的构造方法。
(2)使用 super() 函数
使用 super()
函数可以调用父类的构造方法。
使用格式如下所示:
super().__init__(...)
对以上格式说明,
- 多继承中,super() 函数只能调用第一个直接父类的构造方法。
举例如下所示:
class People:
def __init__(self):
print('People 父类中的构造方法。')
class Animal:
def __init__(self):
print('Animal 父类中的构造方法。')
# 定义一个 Person 子类,继承 People 类和 Animal 类
class Person(People, Animal):
def __init__(self):
super().__init__() # 会调用第一个直接父类的构造方法
print('Person 子类中的构造方法。')
person = Person() # 实例化子类
运行结果:
People 父类中的构造方法。
Person 子类中的构造方法。