本文来自异想之旅公开发布的Python教程,原文地址:https://www.yuque.com/yxzl/python
在前面的示例中,我们一直在使用Student这个类。现在我们的需求升级了,不但需要在Student中加入更多的属性和方法,还需要新增一个Teacher类。按照之前的思路,我们可以这么书写:
class Student:
name = ''
age = 0
gender = ''
grade = 1
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def say_hello(self):
print('Hello!')
def introduction(self):
print('Hello, I am student', self.name)
class Teacher:
name = ''
age = 0
gender = ''
subject = ''
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def say_hello(self):
print('Hello!')
def introduction(self):
print('Hello, I am teacher', self.name)
我们发现,这两个类有着许多十分相似的地方:name``age``gender三个相容的属性,__init__``say_hello两个相同的方法,以及两个相似的introduction方法。
我们考虑定义一个类People,它将实现Student和Teacher共有的部分:
class Person:
name = ''
age = 0
gender = ''
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def say_hello(self):
print('Hello!')
class Student(Person):
grade = 1
def introduction(self):
print('Hello, I am student', self.name)
class Teacher(Person):
subject = ''
def introduction(self):
print('Hello, I am teacher', self.name)
看,将公共部分抽离后代码简短了一些,也变得更加直观了。现在我们希望我们在定义Student和Teacher时可以直接将People的属性和方法也“据为己有”——即继承Person已有的属性和方法,加上自己新增的,成为一个新的类。
我们在后面跟上一个括号,括号中写上要被继承的类。这一过程便被称为类的继承。Person被称作Student和Teacher的父类,而Student和Teacher分别为Person的子类。一个类的子类和父类都可以有多个。
在上面的代码后面执行这段代码,会得到这样的输出:
student = Student('小明', 10, '男')
student.say_hello() # Hello
student.introduction() # Hello, I am student 小明
teacher = Teacher('小红', 20, '女')
teacher.say_hello() # Hello
teacher.introduction() # Hello, I am teacher 小红
现在要对Teacher类的say_hello方法进行更改:将输出的内容改为'Hello students!'。
我们发现,这样一来Teacher中的say_hello方法和Student中不一样了,而继承的部分一定是统一的才行。我们要将Person中的say_hello方法重新放回两个类中去分别定义吗?
自然,对于这个只有Teacher和Student两个类的示例,这样写也是可以的,但是假设我们还有Worker等等一些其它的、也同时都继承自Person的类,这样操作就太麻烦了。我们可以对类的方法进行重写。
class Person:
name = ''
age = 0
gender = ''
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def say_hello(self):
print('Hello!')
class Student(Person):
grade = 1
def introduction(self):
print('Hello, I am student', self.name)
class Teacher(Person):
subject = ''
def say_hello(self):
print('Hello students!')
def introduction(self):
print('Hello, I am teacher', self.name)
student = Student('小明', 10, '男')
student.say_hello() # Hello
student.introduction() # Hello, I am student 小明
teacher = Teacher('小红', 20, '女')
teacher.say_hello() # Hello students!
teacher.introduction() # Hello, I am teacher 小红
我们在子类Teahcer中定义了一个和父类中方法重名的方法,Python 会自动使用子类中的定义而抛弃父类中的定义。
一个类可以通过 super() 调用其继承的类的函数:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Student(Person):
def __init__(self, name, age, grade):
self.grade = grade
super().__init__(name, age)
super() 可以传入两个参数,分别代表从哪个类向后找和传入的 self
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Student(Person):
def __init__(self, name, age, grade):
self.grade = grade
super().__init__(name, age)
# 上面一行语句等价于
super(Student, self).__init__(name, age)
比如我们有Person继承Animal,Student继承Person,想要在Student里调用Animal的函数,可以如下使用:
class Animal:
def __init__(self, age):
self.age = age
class Person(Animal):
def __init__(self, name):
self.name = name
class Student(Person):
def __init__(self, name, age, grade):
self.grade = grade
super(Student, self).__init__(name)
super(Person, self).__init__(age)
# 当然,上面只是一个演示,实际上这个例子应该这样写:
class Animal:
def __init__(self, age):
self.age = age
class Person(Animal):
def __init__(self, name, age):
self.name = name
super().__init__(age)
class Student(Person):
def __init__(self, name, age, grade):
self.grade = grade
super().__init__(name, age)
super的全局使用除了类的方法内部,在 Python 代码的任意位置都可以调用super()函数。只不过,在方法之外的位置使用必须完整传递两个参数:
class People:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
def say_hello(self):
print('Hello!')
class Teacher(People):
subject = ''
def say_hello(self):
print('Hello students!')
teacher = Teacher('小红', 20, '女')
teacher.say_hello() # Hello students!
super(Teacher, teacher).say_hello() # Hello!