类的继承
类的继承
什么是继承
- 继承是一种新建类的方式,新建的类称为子类,被继承的类称为父类
- 继承的特性是:子类会遗传父类的属性或方法
- 继承是类与类之间的关系
为什么用继承
- 使用继承可以减少代码的冗余
如何用继承
class School: # 父类
pass
class Student(School): # 子类
pass
print(Student.__bases__)
print(School.__bases__)
# (<class '__main__.School'>,)
# (<class 'object'>,)
注意:
- 在 python 3中如果一个类没有继承任何类,则默认继承 object 类。
- 在 python 2中如果一个类没有继承任何类,不会继承 object 类。
继承与抽象
继承:子类继承父类,描述的是子类与父类之间的关系,是一种什么是什么的关系。
抽象:不具体,不清晰。将多个子类中相同的部分进行抽取,形成一个新类。
正确使用继承:
1:先抽象再继承。
2:继承一个已经现存的类,扩展或修改原始的功能。
继承的应用
# 在python中,一个子类可以同时继承多个父类
class OldboyPeople: # 父类
school = 'oldboy'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Student(OldboyPeople): # 子类
def study(self):
print('%s同学正在学习'%self.name)
class Teacher(OldboyPeople): # 子类
def teaching(self):
print('%s老师正在教书'%self.name)
stu = Student('zkim', 20, '男')
stu.study()
tea = Teacher('jason', 18, '男')
tea.teaching()
# zkim同学正在学习
# jason老师正在教书
属性查找
class A:
text = 'from A'
class B(A):
text = 'from B'
b = B()
b.text = 'from b'
print(b.text)
# from b
查找循序:对象本身—>所在的类—>父类—>父类的父类—>object
类的派生
派生是什么
- 派生:子类中新定义的属性的这个过程叫做派生,并且需要记住子类在使用派生的属性时始终以自己的为准。
- 派生的用法一:
class OldboyPeople:
school = 'oldboy'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Student(OldboyPeople):
def __init__(self, name, age, gender, number):
OldboyPeople.__init__(self, name, age, gender)
self.number = number
stu = Student('zkim', 20, '男', 11)
print(stu.__dict__)
# {'name': 'zkim', 'age': 20, 'gender': '男', 'number': 11}
- 派生的用法二(super):
- 严格以来继承属性查找关系
- super()会得到一个特殊的对象,该对象就是专门用来访问父类中的属性的(按照继承的关系)
- super().init(不用为self传值)
- super的完整用法是super(自己的类名,self),在python2中需要写完整,而python3中可以简写为super()
class OldboyPeople:
school = 'oldboy'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Student(OldboyPeople):
def __init__(self, name, age, gender, number):
super().__init__(name, age, gender)
# super(Student, self).__init__(name, age, gender)
self.number = number
stu = Student('zkim', 20, '男', 11)
print(stu.__dict__)
# {'name': 'zkim', 'age': 20, 'gender': '男', 'number': 11}
- 覆盖:覆盖也称之为重写 overrides,当子类出现了与父类名称完全一样的属性或方法。
- 注意:当你继承一个现有的类,并且你覆盖了父类的 _init_ 方法时,必须在初始化方法的第一行调用父类的初始化方法,并传入父类所需的参数 。
类
类的组合
什么是组合
- 组合:组合也是一种关系,描述两个对象之间是什么有什么的关系。就是将一个对象作为另一个对象的属性。
为什么用组合
- 为了重用现有的代码
- 组合相比较继承,耦合度更低了。
如何用组合
# 假设我们有个手机,那么不适用继承如何使用手机呢。
class Phone: # 手机
def __init__(self,price,brand,model):
self.price = price
self.brand = brand
self.model = model
def call(self):
print('正在呼叫...')
class Person: # 人
def __init__(self,name,age,gender,phone):
self.name = name
self.age = age
self.gender = gender
self.phone = phone
phone = Phone(1600,'华为','荣耀play')
person = Person('zkim',21,'男',phone)
person.phone.call()
# 正在呼叫...
菱形继承
类的分类
- 新式类:继承了object 的类以及该类的子类都是是新式类。python 3中所有的类都是新式类。
- 经典类:没有继承 object 的类都是经典类。只有python 2中才有经典类。
菱形继承问题
当继承关系为菱形结构,即子类的父类最后继承了同一个类,那么属性的查找方法有:
- 经典类下:广度优先
class A:
x = 1 # 最后找父类的父类 A
class B(A):
x = 2 # 3.找父类 B
class C(A):
x = 3 # 4.找父类 C
class D(A):
x = 4 # 5.找父类 D
class E(B,C,D):
x = 5 # 2.再找所在的类
e = E()
e.x = 6 # 1.先找对象本身
print(e.x)
# 6
千里之行,始于足下。