主要内容:
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]
'''