面向对象-继承与派生
1.2python中类的继承分类:单继承和多继承继承指的是类与类之间的关系,是一种什么“是”什么的关系,继承的功能之一就是用来解决代码重用问题。
继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类可以成为基类或超类,新建的类成为派生类或子类
class ParentClass1: #定义父类 passclass ParentClass2: #定义父类 passclass SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass passclass SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类 pass
1.3查看继承
"__base__只查看从左到右继承的第一个父类__bases__查看所有继承的父类"#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: vitaclass ParentClass1: #定义父类 passclass ParentClass2: #定义父类 passclass SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass passclass SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类 passprint(SubClass1.__base__)print(SubClass2.__base__)print(SubClass1.__bases__)print(SubClass2.__bases__)E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py<class '__main__.ParentClass1'><class '__main__.ParentClass1'>(<class '__main__.ParentClass1'>,)(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)Process finished with exit code 0
1.4经典类与新式类
1.只有在Python2中才有新式类和经典类,Python3中全部都是新式类2.在Python2中,如果没有显式的继承object类,那该类和其子类都是经典类3.在Python2中,如果显式的继承object类,那该类和其子类都是新式类4.在Python3中,无论是否继承object,都默认继承object,即Python3中所有类都是新式类5.在Python3中,如果没有指定基类,会默认继承object类,object是所有Python类的基类print(ParentClass1.__bases__)print(ParentClass2.__bases__)E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py(<class 'object'>,)(<class 'object'>,)Process finished with exit code 0
2.抽象与继承
抽象:抽取类似的部分,主要用于划分类别
3.继承与重用继承:基于抽象的结果,通过编程语言去实现它,所以需要先对事物或逻辑进行抽象,之后通过继承的方式表达出抽象的结构
在开发中,如果类A与类B有很多相同的代码,就可以通过继承来实现,提高代码的重用性
可以让B继承A,B会‘遗传’A的所有属性(包含数据属性和函数属性)
#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: vitaclass Hero: def __init__(self,nickname,aggressivity,life_value): self.nickname=nickname self.aggressivity=aggressivity self.life_value=life_value def attack(self,enemy): enemy.life_value-=self.aggressivityclass Garen(Hero): passclass Riven(Hero): passg1=Garen('草丛伦',100,300)r1=Riven('锐雯雯',57,200)print(g1.life_value) #结果:300r1.attack(g1)print(g1.life_value) #结果:243E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py300243Process finished with exit code 0"用已经有的类新建一个新的类,这样就可以重用已经有的软件中的部分代码,大大节省编程工作量,这就是软件重用,不仅可以重用自己的类,还可以继承别人写的类,也可继承标准库。"
4.属性查找与self深入理解
不管是类中的数据属性还是函数属性,都是先在自己的类中查找,没有,再到父类中查找
#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: vitaclass Foo: def f1(self): print('Foo.f1') def f2(self): print('Foo.f2') self.f1()class Bar(Foo): def f1(self): print('Bar.f1')b=Bar()#f2()在Bar类中没有,就去父类Foo中找,父类中的f2又调用self.f1,同样先去自己的类中找,找到了,就返回。b.f2()E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.pyFoo.f2Bar.f1Process finished with exit code 0
子类也可以添加自己的新属性或重新定义父类中含有的数据属性和函数属性,子类中新定义的属性对父类中的属性是没有影响的,但一旦重新定义的自己的属性与父类中的属性重名,调用新的属性就以自己的为准了
#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: vitaclass Hero: def __init__(self,nickname,aggressivity,life_value): self.nickname=nickname self.aggressivity=aggressivity self.life_value=life_value def attack(self,enemy): enemy.life_value-=self.aggressivityclass Garen(Hero): passclass Riven(Hero): camp='Noxus' def attack(self,enemy): #在自己这里定义新的attack,不再使用父类的attack,且不会影响父类 print('from riven') def fly(self): #在自己这里定义新的 print('%s is flying' %self.nickname)g1=Garen('草丛伦',100,300)r1=Riven('锐雯雯',57,200)r1.attack(g1)E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.pyfrom rivenProcess finished with exit code 0
在子类中,新建了与父类中重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中的同名的那个函数,此时调用父类中同名函数的方法:类名.func(),此时就与调用普通函数相同了,因此self也要为其传值
#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: vitaclass Hero: def __init__(self,nickname,aggressivity,life_value): self.nickname=nickname self.aggressivity=aggressivity self.life_value=life_value def attack(self,enemy): enemy.life_value-=self.aggressivityclass Garen(Hero): passclass Riven(Hero): camp='Noxus' def __init__(self,nickname,aggressivity,life_value,skin): Hero.__init__(self,nickname,aggressivity,life_value) #调用父类功能 self.skin=skin #新属性 def attack(self,enemy): #在自己这里定义新的attack,不再使用父类的attack,且不会影响父类 Hero.attack(self,enemy) #调用功能 print('from riven') def fly(self): #在自己这里定义新的 print('%s is flying' %self.nickname)r1=Riven('锐雯雯',57,200,'比基尼')r1.fly()print(r1.skin)E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py锐雯雯 is flying比基尼Process finished with exit code 0
6.深度优先与广度优先6.1MRO列表介绍
上面我们一直在说,对于数据属性和函数属性的查找,首先找对象自身的定义空间,即对象.__dict__的结果,如果没有,去自己的类中找,自己类中没有,再去父类中找。但是当继承比较复杂,有多个父类,父类还有父类,这种情况下是怎样的一个查找顺序呢?python有一个方法解析顺序表(MRO),这个MRO列表就是一个属性的查找顺序列表,找到了相关的属性就停止查找,否则就一直按照这个顺序找到最后,找不到,就报错了>>> F.mro() #等同于F.__mro__[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]MRO列表遵循三条准则:1.子类优先于父类被检查2.多个父类会根据他们在列表中的顺序去检查3.如果下一个类中存在两个合法的选择,选择第一个父类
6.2新式类与经典类
#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: vitaclass A(object): def test(self): print('from A')class B(A): def test(self): print('from B')class C(A): def test(self): print('from C')class D(B): def test(self): print('from D')class E(C): def test(self): print('from E')class F(D,E): # def test(self): # print('from F') passf1=F()f1.test()print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性#新式类继承顺序:F->D->B->E->C->A#经典类继承顺序:F->D->B->A->E->C#python3中统一都是新式类#pyhon2中才分新式类与经典类E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.pyfrom D(<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)Process finished with exit code 0
"当C不继承A了,新式类与经典类的顺序就相同了"#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: vitaclass A(object): def test(self): print('from A')class B(A): def test(self): print('from B')class C: def test(self): print('from C')class D(B): def test(self): print('from D')class E(C): def test(self): print('from E')class F(D,E): # def test(self): # print('from F') passf1=F()f1.test()print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.pyfrom D(<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.E'>, <class '__main__.C'>, <class 'object'>)Process finished with exit code 0
7.子类中调用父类的方法7.1方式一:指名道姓,即父类名.方法名
#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: vitaclass Vehicle: # 定义交通工具类 Country = 'China' def __init__(self, name, speed, load, power): self.name = name self.speed = speed self.load = load self.power = power def run(self): print('开动啦...')class Subway(Vehicle): # 地铁 def __init__(self, name, speed, load, power, line): Vehicle.__init__(self, name, speed, load, power)# 指名道姓方式,调用父类中同名的方法 self.line = line def run(self): print('地铁%s号线欢迎您' % self.line) Vehicle.run(self)# 指名道姓方式,调用父类中同名的方法line13 = Subway('中国地铁', '180m/s', '1000人/箱', '电', 13)line13.run()E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py地铁13号线欢迎您开动啦...Process finished with exit code 0
7.2super()方式
#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: vitaclass Vehicle: # 定义交通工具类 Country = 'China' def __init__(self, name, speed, load, power): self.name = name self.speed = speed self.load = load self.power = power def run(self): print('开动啦...')class Subway(Vehicle): # 地铁 def __init__(self, name, speed, load, power, line): # super(Subway,self) # Python2的写法 在python3中super()等同于super(Subway,self) super().__init__(name, speed, load, power) self.line = line def run(self): print('地铁%s号线欢迎您' % self.line) #super(Subway, self).run()# Python2的写法 super().run() #Python3中,可以不在super()中写类名和selfclass Mobike(Vehicle): # 摩拜单车 passline13 = Subway('中国地铁', '180m/s', '1000人/箱', '电', 13)line13.run()E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py地铁13号线欢迎您开动啦...Process finished with exit code 0
7.3两种方式的区别
"方式一与属性查找的mro顺序没有关系,直接指定了调用哪个类中的方法方式二是会按照mro列表中的顺序,向后查找相应的属性"#!/usr/bin/env python# -*- coding:utf-8 -*-# Author: vita# "A没有继承B,但是A内super会基于C.mro()继续往后找"class A: def test(self): super().test()class B: def test(self): print('from B')class C(A,B): passc=C()c.test() #打印结果:from Bprint(C.mro())E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.pyfrom B[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]Process finished with exit code 0
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。