目录
Python面向对象03/继承
内容大纲
1.初识继承
2.继承的优点
3.单继承
4.多继承
1.初识继承
#字面上的意思是儿子完全使用父亲的所有内容#专业角度:如果B类继承A类# B类就称为子类,派生类# A类就称为父类,超类,基类面向对象的三大特征: 继承,封装,多态#继承可以分为单继承/多继承
2.继承的优点
#1.减少重复的代码#2.增加类之间的耦合性(不宜多,宜精)#3.使代码更清晰,合理化
3.单继承
3.1类名执行父类的属性和方法
3.2派生类对象,执行父类的属性和方法
#查询顺序:# 单向不可逆,子类可以使用父类的属性和方法,父类不可以使用子类的属性和方法实例化对象时必须执行__init__方法,类中没有,从父类找,父类没有,从object类中找。
3.3既要执行子类的方法,又要执行父类的方法
方法一:不依赖继承 父类.func(对象,其他参数)#class Animal(object):# type_name = "动物类"# def __init__(self,name,sex,age):# self.name = name# self.age = age# self.sex = sex# def eat(self):# print("吃东西")# class Person(Animal):# def __init__(self,name,sex,age,mind):# Animal.__init__(self,name,sex,age)# self.mind = mind# def eat(self):# super().eat()# print(f'{self.name}会吃饭')# # p1 = Person("二狗","男",18,"有思想")# p1.eat()方法二:依赖继承 利用super,super().func(参数) super.__init__执行父类 执行父类的__init__方法,重构父类方法.#class Aniaml(object):# type_name = '动物类'# def __init__(self,name,sex,age):# self.name = name# self.age = age# self.sex = sex# def eat(self):# print('吃东西')#class Person(Aniaml):# def __init__(self,name,sex,age,mind):# {super(Person,self).__init__(name,sex,age)} (完整写法) # super().__init__(name,sex,age)# self.mind = mind# def eat(self):# super().eat()# print('%s 吃饭'%self.name)#class Cat(Aniaml):# pass# p1 = Person('二狗','男',18,'有思想')# print(p1.__dict__)练习一:# class Base:# def __init__(self,num):# self.num = num# def func1(self):# print(self.num)# class Foo(Base):# pass# obj = Foo(123)# obj.func1()练习二:# class Base:# def __init__(self,num):# self.num = num# def func1(self):# print(self.num)# class Foo(Base):# def func1(self):# print("Foo.func1",self.num)# obj = Foo(123)# obj.func1()练习三:# class Base:# def __init__(self,num):# self.num = num# def func1(self):# print(self.num)# self.func2()# def func2(self):# print("Base.func2")# class Foo(Base):# def func2(self):# print("Foo.func2")# obj = Foo(123)# obj.func1()练习四:# class Base:# def __init__(self,num):# self.num = num# def func1(self):# print(self.num)# self.func2()# def func2(self):# print(111,self.num)# class Foo(Base):# def func2(self):# print(222,self.num)# lst = [Base(1),Base(2),Foo(3)]# for obj in lst:# obj.func2()练习五:# class Base:# def __init__(self,num):# self.num = num# def func1(self):# print(self.num)# self.func2()# def func2(self):# print(222,self.num)# class Foo(Base):# def func2(self):# print(222,self.num)# lst = [Base(1),Base(2),Foo(3)]# for obj in lst:# obj.func1()
4.多继承
Python类分为两种: 1.经典类: 不继承object类,深度优先原则 2.新式类: 继承object类,mro(C3)算法(新式类查询顺序)Python2x: Python2.2之前都是经典类,Python2.2之后,经典类和新式类共存Python3x: 全都是新式类,如果基类谁都不继承,那这个类会默认继承object类 # class Shenxian:# def fly(self):# print("神仙都会飞")# class Monkey:# def climb(self):# print("猴子会爬树")# class Sunwukong(Shenxian,Monkey):# pass# sxz = Sunwukong()# sxz.climb()# sxz.fly() # 经典类: 深度优先.从左至右,深度优先.class O: name = '太白'class D(O): passclass E(O): name = '李业' # passclass F(O): name = '宝元'class B(D,E): passclass C(E,F): passclass A(B,C): passobj = A()print(obj.name)# mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )# mro(A(B,C)) = [A] + merge(mro(B),mro(C),[B,C])'''mro(A(B,C)) = [A] + merge(mro(B),mro(C),[B,C])mro(B(D,E)) = [B] + merge(mro(D),mro(E),[D,E])mro(B(D,E)) = [B] + merge([D,O],[E,O],[D,E])mro(B(D,E)) = [B,D] + merge([O],[E,O],[E])mro(B(D,E)) = [B,D,E] + merge([O],[O])mro(B(D,E)) = [B,D,E,O]mro(C) = [C,E,F,O]mro(A(B,C)) = [A] + merge([B,D,E,O],[C,E,F,O],[B,C]) = [A,B] + merge([D,E,O],[C,E,F,O],[C]) = [A,B,D] + merge([E,O],[C,E,F,O],[C]) = [A,B,D,C] + merge([E,O],[E,F,O]) = [A,B,D,C,E] + merge([O],[F,O]) = [A,B,D,C,E,F,O] '''# print(A.mro())
在python2x版本中存在两种类.: ⼀个叫经典类. 在python2.2之前. ⼀直使⽤的是经典类. 经典类在基类的根如果什么都不写. ⼀个叫新式类. 在python2.2之后出现了新式类. 新式类的特点是基类的根是object类。python3x版本中只有一种类:python3中使⽤的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object
5.今日练习
# 1.简答题:# 1.面向对象的三大特性是什么?# 继承,封装,多态# 2.什么是面向对象的新式类?什么是经典类?# 新式类:如果基类谁都不继承,那这个类会默认继承object# 经典类:不继承object类,深度优先原则# 3.面向对象为什么要有继承?继承的好处是什么?# 1.减少重复代码# 2.增加类之间的耦合性# 3.使代码更清晰,合理化# 4.面向对象中super的作用。# super().func(参数) 重构父类的方法## 2.代码题(通过具体代码完成下列要求):# class A:# def func(self):# print('in A')# class B:# def func(self):# print('in B')# class C(A, B):# def func(self):# print('in C')#可以改动上上面代码,完成下列需求:对C类实例化一个对象产生一个c1,然后c1.func()#1.让其执行C类中的func#2.让其执行A类中的func#3.让其执行B类中的func#4.让其既执行C类中的func,又执行A类中的func#5.让让其既执行C类中的func,又执行B类中的func# 1.# c1 = C()# c1.func()# 2.# A.func(111)# 3.# B.func(111)# 4.# class A:# def func(self):# print('in A')# class B:# def func(self):# print('in B')# class C(A, B):# def func(self):# super().func()# print('in C')# c1 = C()# c1.func()# 5.# class A:# def func(self):# print('in A')# class B:# def func(self):# print('in B')# class C(A, B):# def func(self):# super(A,self).func()# print('in C')# c1 = C()# c1.func()#3.下面代码执行结果是什么?为什么?# class Parent:# def func(self):# print('in Parent func')# def __init__(self):# self.func()# class Son(Parent):# def func(self):# print('in Son func')# son1 = Son()# in Son func#4.# class A:# name = []# p1 = A()# p2 = A()# p1.name.append(1)# p1.name,p2.name,A.name 分别是什么?# [1],[1],[1]类的静态属性,如果指向一个可变数据类型,对象或者类名都可以给这个可变数据类型内部增,删,改,查(不可以对其整体增,删,改,查)# p1.age = 12# p1.age,p2.age,A.age 分别又是什么?为什么?# 12 ,报错,报错#5.写出下列代码执行结果:# class Base1:# def f1(self):# print('**base1.f1**')## def f2(self):# print('**base1.f2**')## def f3(self):# print('**base1.f3**')# self.f1()# class Base2:# def f1(self):# print('**base2.f1**')# class Foo(Base1, Base2):# def f0(self):# print('**foo.f0**')# self.f3()# obj = Foo()# obj.f0()# **'foo.f0' **# **'base1.f3' **# **'base1.f1' **#5. 看代码写结果:# class Parent:# x = 1# class Child1(Parent):# pass# class Child2(Parent):# pass# print(Parent.x, Child1.x, Child2.x)# 1 1 1# Child2.x = 2# print(Parent.x, Child1.x, Child2.x)# 1 1 2# Child1.x = 3# print(Parent.x, Child1.x, Child2.x)# 1 3 2## 6.有如下类:# class A:# pass# class B(A):# pass# class C(A):# pass# class D(A):# pass# class E(B, C):# pass# class F(C, D):# pass# class G(D):# pass# class H(E, F):# pass# class I(F, G):# pass# class K(H, I):# pass# 如果这是经典类,请写出他的继承顺序。# KHEBACFDIG## 如果这是新式类,请写出他的继承顺序,并写出具体过程。# KHEBIFCGDA
经典类流程图