晚上都睡不着了,和萧敬腾一样,我睡了一觉却更觉得疲劳
打气!草 他 妈 的!打气!
今日洗脑金句:!!@#%¥……@!@%#¥!%
类的继承
一、什么是继承
- 继承是一种新建类的方式,新建的类称为子类,被继承的类称为父类
- 继承的特性是:子类会遗传父类的属性
- 继承是类与类之间的关系
简单来讲,我是你爸爸,你是我儿子,你就继承了我的东西,我的一屁股债,以及我的脑子。
二、为什么要用继承
- 使用继承可以减少代码的冗余(别问,问就是爸爸爱你)
三、对象的继承
- Python中支持一个类同时继承多个父类
class Parent1:
pass
class Parent2:
pass
class Sub1(Parent1, Parent2):
pass
。。。。你究竟是谁的儿子
- 使用__bases__方法可以获取对象继承的类
print(Sub1.__bases__)
(<class 'main.Parent1'>, <class 'main.Parent2'>)
- 在Python3中如果一个类没有继承任何类,则默认继承object类
- 在Python2中如果一个类没有继承任何类,不会继承object类
print(Parent1.__bases__)
(<class 'object'>,)
四、类的分类
新式类:就是继承了object的类以及该类的子类,都是新式类,而且python3里面只有新式类,所有的都是。不存在经典类。
经典类:没有继承object的类以及该类的子类,都是经典类,只有python2中才有经典类。
五、对象查找属性的顺序
- 对象查找属性的顺序:对象自己-》对象的类-》父类-》父类。。。
类的派生
一、派生是什么
- 派生:子类中新定义的属性的这个过程叫做派生,并且需要记住子类在使用派生的属性时始终以自己的为准
1.1派生方法一(类调用)
- 指名道姓访问某一个类的函数:该方式与继承无关
class OldboyPeople:
"""由于学生和老师都是人,因此人都有姓名、年龄、性别"""
school = 'oldboy'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class OldboyStudent(OldboyPeople):
"""由于学生类没有独自的__init__()方法,因此不需要声明继承父类的__init__()方法,会自动继承"""
def choose_course(self):
print('%s is choosing course' % self.name)
class OldboyTeacher(OldboyPeople):
"""由于老师类有独自的__init__()方法,因此需要声明继承父类的__init__()"""
def __init__(self, name, age, gender, level):
OldboyPeople.__init__(self, name, age, gender)
self.level = level # 派生
def score(self, stu_obj, num):
print('%s is scoring' % self.name)
stu_obj.score = num
stu1 = OldboyStudent('tank', 18, 'male')
tea1 = OldboyTeacher('nick', 18, 'male', 10)
print(stu1.__dict__)
print(tea1.__dict__)
{'name': 'tank', 'age': 18, 'gender': 'male'}
{'name': 'nick', 'age': 18, 'gender': 'male', 'level': 10}
1.2 派生方法二(super)
- 严格以来继承属性查找关系
- super()会得到一个特殊的对象,该对象就是专门用来访问父类中的属性的(按照继承的关系)
- super().__init__(不用为self传值)
- super的完整用法是super(自己的类名,self),在python2中需要写完整,而python3中可以简写为super()
class OldboyPeople:
school = 'oldboy'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class OldboyStudent(OldboyPeople):
def __init__(self, name, age, sex, stu_id):
# OldboyPeople.__init__(self,name,age,sex)
# super(OldboyStudent, self).__init__(name, age, sex)
super().__init__(name, age, sex)
self.stu_id = stu_id
def choose_course(self):
print('%s is choosing course' % self.name)
stu1 = OldboyStudent('tank', 19, 'male', 1)
print(stu1.__dict__)
{'name': 'tank', 'age': 19, 'sex': 'male', 'stu_id': 1}
通常情况下本大爷都是用super()的,java后遗症,感觉用第一种方式的话和继承没一点关系,用个几把呢?
菱形继承问题
这张图看得懂吗,你肯定看不懂。[img](https://images.cnblogs.com/cnblogs_com/chanyuli/1515439/o_(%60@Z%7DIR0[1[~(~SX8CB)3CN.jpg)
就是寻找的顺序啦。
A继承了BCD三个父类,怎么找属性呢,按顺序来,从左到右,从下到上,真色情啊,就是上面这个图的意思了。
但是,这是python2里的搜索方式,也叫深度优先搜索,找到一个父类,直接干到底,再去干第二个父类。
而在python3里,是广度优先搜索
一旦发现自己要访问的下一个父类,有其他也会去访问,直接停住,开始走下一个父类,直到最后全部会访问完,这就是python3的广度优先搜索。
python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,如:
print(A.mro()) # A.__mro__
[<class 'main.A'>, <class 'main.B'>, <class 'main.E'>, <class 'main.C'>, <class 'main.F'>, <class 'main.D'>, <class 'main.G'>, <class 'object'>]
也可以用这个方法来看他搜索的顺序。
好了,话不多说,几千字就够,仔细一看,这篇博客也写的挺好的,他好就好在他好tmgb