python -- 继承
主要内容:
1.继承
2.新式类与经典类
3.多继承的优先查询
一.继承
定义一个类,class Dog(Animal) 其中括号里面的Animal是父类/基类/超类,括号外面的Dog是子类/派生类.
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类.
当我们在定义多个类的时候,发现要用到相同的方法或变量,如果每个类都要写相同的方法和变量,那么代码就会重复,为了减少代码,可以用继承来解决.
# encoding:utf-8
# 如果是用的python2,python2默认使用ascii码,先再第一行写上encoding:utf-8 ;
# python3默认使用的是utf-8
组合:让一个类对象与另一个类的对象发生关系
继承:让类与类发生关系
面向对象的三大特性: 继承 多态 封装
面向对象为什么要有继承?继承的好处是什么?
a, 提高了代码的复用性
b:提高了代码的维护性
c:让类与类之间产生了关系,是多态的前提
# 子类以及子类实例化的对象 可以访问父类的任何方法或变量.
# 类名可以访问父类所有内容
# 子类实例化的对象也可以访问父类所有内容
# 父类不能访问子类的东西
#这几个类用到了相同的方法和变量,为了提高代码的复用性,引入继承的思想 class Animal: def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age class Person: def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age class Cat: def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age class Dog: def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age
class Animal: breath = '呼吸' def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age def eat(self): print(self) print('动物都需要进食....') class Person(Animal): # 括号里面的 父类,基类,超类 括号外面的 子类,派生类. pass class Cat: pass class Dog: pass p1 = Person('alex', 'laddyboy', 1000) print(p1.__dict__) #{'name': 'alex', 'sex': 'laddyboy', 'age': 1000} # 初识继承: # 子类以及子类实例化的对象 可以访问父类的任何方法或变量. # 类名可以访问父类所有内容 print(Person.breath) #呼吸 Person.eat(111) #111 #动物都需要进食.... # 子类实例化的对象也可以访问父类所有内容 print(p1.breath) #呼吸 print(p1) #<__main__.Person object at 0x0000006ECD9A7C88> p1.eat() #<__main__.Person object at 0x0000006ECD9A7C88> #动物都需要进食....
查询顺序:子类的对象空间==>子类空间==>父类空间
只执行父类的方法:子类中不要定义与父类同名的方法
只执行子类的方法:在子类创建这个方法.
既要执行子类的方法,又要执行父类的方法?
有两种解决方法.
1,Animal.__init__(self, 参数)
2,super().__init__(参数)
class Animal: def __init__(self,name): self.name=name # def eat(self): # print("会") def eat(self): print("%s会吃" %self.name) def drink(self): print("%s会喝" %self.name) class Cat(Animal): def tian_zhua_zi(self): print("%s会舔爪子" %self.name) class Dog(Animal): def kan_jia(self): print("%s会看家" %self.name) class Chicken(Animal): def xia_dan(self): print("%s会下蛋" %self.name) class Bird(Animal): def __init__(self,name,wing): #self=Bird的实例化对象b, name="鹦鹉", wing="绿翅膀" #Animal.__init__(self,name) #类名.函数+(),,相当于函数的调用,()里面装的是实参,把self,name当做实参传进来 # (self现在是指Bird的对象b,也就是个空间地址),然后执行函数,父类的函数对name进行封装,函数执行完毕, # 执行下一步,self.wing=wing,是Bird自身对对象的属性进行封装. super().__init__(name)#super(Bird,self).__init__(name) 用super()直接把想要的父类的参数拿过来,然后封装自己的参数 self.wing=wing print(name,wing) def eat(self): super().eat() print("%s会吃小虫子" % self.name) # c=Cat() #父类中没有__init__方法,实例化一个子类的对象,子类的对象调用父类的方法,也会执行父类方法中的内容 # c.eat() # c=Cat("猫") # c.eat() # c.drink() # c.tian_zhua_zi() # # d=Dog("狗") # d.eat() # d.drink() # d.kan_jia() # # j=Chicken("鸡") # j.eat() # j.drink() # j.xia_dan()
二.新式类与经典类
继承: 单继承,多继承.
单继承:只继承一个父类
class A(B):
pass
多继承:继承两个及两个以上的父类
class A(B,C):
pass
类: 经典类, 新式类
新式类: 凡是继承object类都是新式类.
python3x 所有的类都是新式类,因为python3x中的类都默认继承object.
经典类: 不继承object类都是经典类
python2x:(既有新式类,又有经典类) 所有的类默认都不继承object类,所有的类默认都是经典类.你可以让其继承object.
三.多继承的优先查询
1.单继承: 新式类,经典类查询顺序一样.
2.多继承:
新式类: 遵循广度优先.
经典类: 遵循深度优先.
3.多继承的新式类
广度优先 : 一条路走到倒数第二级,判断,如果其他路能走到终点,则返回走另一条路.如果不能,则走到终点.
4.多继承的经典类
深度优先 : 一条路走到底.
5.查询类的继承顺序: 类名.mro()
class A: def func(self): print('IN A') class B(A): pass # def func(self): # print('IN B') class C(A): pass # def func(self): # print('IN C') class D(B): pass # def func(self): # print('IN D') class E(C): pass # def func(self): # print('IN E') class F(D,E): pass # def func(self): # print('IN F') f1 = F() print(F.mro()) #[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
6.多继承广度优先查询算法
#例子1
class H: pass class G(H): pass class F(H): pass class E(G): pass class D(F): pass class C(E): pass class B(D): pass class A(B, C, D): pass print(A.mro()) ''' 首先找到A继承的三个类的深度继承顺序,放到一个列表中 B [B,D,F,H] C [C,E,G,H] D [D,F,H] 每个列表的第一个元素为头部,其它位置元素都为尾部,从第一个列表的头部开始找,找其他列表中尾部是否含有 这个类名,如果没有,提取出来放到一个列表中,如果有,找下一个列表的头部,循环下去 只要提取来一个,我们就从第一个列表的头部接着重复上面的操作. A [A] [B,D,F,H] [C,E,G,H] [D,F,H] [B,C,D] A #找到第一个列表的头A,其他列表尾部没有A,把A取出来,如果其他列表的头部有A则剔除 [] [B,D,F,H] [C,E,G,H] [D,F,H] [B,C,D] B [] [D,F,H] [C,E,G,H] [D,F,H] [C,D] C [] [D,F,H] [E,G,H] [D,F,H] [D] D [] [F,H] [E,G,H] [F,H] [] F [] [H] [E,G,H] [H] [] E #找到第一个列表的头部H,但是其他列表尾部有H,所以跳过这个列表,去下一个列表取头部 [] [H] [G,H] [H] [] G [] [H] [H] [H] [] H [] [] [] [] [] lst = [A,B,C,D,F,E,G,H] '''
#例子2
class F: pass class E: pass class D: pass class C(D, F): pass class B(E, D): pass class A(B, C): pass print(A.mro()) ''' 首先找到A继承的两个类的深度继承顺序 把B作为子类,找出B类的查询顺序 B [B] [E] [D] [E,D] B [] [E] [D] [E,D] E [] [] [D] [D] D [] [] [] []
lst = [B,E,D] 把C作为子类,找出C类的查询顺序 C [C] [D] [F] [D,F] C [] [D] [F] [D,F] D [] [] [F] [F] F [] [] [] [] lst = [C,D,F] A [A] [B,E,D] [C,D,F] [B,C] A [] [B,E,D] [C,D,F] [B,C] B [] [E,D] [C,D,F] [C] E [] [D] [C,D,F] [C] C [] [D] [D,F] [] D [] [] [F] [] F [] [] [] [] lSt = [A,B,E,C,D,F] '''