python面向对象之继承
2. 继承
继承的第一个作用
第一阶段:继承的作用
class Animal(object):
def run(self):
print("Animal is running")
class Dog(Animal):
pass
class Cat(Animal):
pass
dog = Dog()
cat = Cat()
dog.run()
cat.run()
Animal is running
Animal is running
上面Animal就是父类,子类就是Dog和Cat,因为Dog和Cat继承了Animal,子类会拥有父类的所有方法。
总结:
1. 当子类继承父类后,子类就会拥有父类的所有方法
继承的第二个作用:子类重写方法后,优先调用子类方法
第二阶段:当子类继承父类后,子类写了一个run方法,父类也写了一个run方法,子类调用run方法时,应该调用父类的run还是子类的?
# 子类继承父类的方法
class Animal(object):
def run(self):
print("Animal is running")
class Dog(Animal):
def run(self):
print("Dog is running")
class Cat(Animal):
def run(self):
print("Cat is running")
dog = Dog()
cat = Cat()
# 调用方法
dog.run()
cat.run()
Dog is running
Cat is running
由此可以看出,优先调用子类的方法
总结:
1. 当子类拥有和父类相同的方法时,优先调用子类的方法。
继承的第三个作用:类的派生
class person(object):
def __init__(self, weight):
self.weight = weight
def eat(self):
print("正在吃东西")
class Student(person):
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
a = Student('plf', 18, '男')
a.eat()
print(a.name, a.age, a.sex)
正在吃东西
plf 18 男
对于以上的代码,提出一个疑问:既然Student类继承了person类,那么Student初始化的对象就拥有了person类的方法,但是对应person的属性weight,Student似乎没有继承到,那么我们如何在初始化Student对象时,拥有父类的weight属性?同时拥有不同于父类的属性?
class person(object):
def __init__(self,weight):
self.weight = weight
class Student(person):
def __init__(self,name,age,sex,weight):
self.name = name
self.age = age
self.sex = sex
super().__init__(weight) # 调用了父类的__init__方法,并将weight传给了person
a = Student('plf',18,'男',140)
print(a.name,a.age,a.sex,a.weight)
因此想要得到父类的属性,必须要在子类的初始化方法中(__init__函数)中调用父类的方法:super()._init_(args,*kwargs) 这样就能拿到父类的属性并赋值 最后变成自己的属性,同时子类有不同于父类的属性。子类继承父类,子类有父类的属性,且子类有不同于父类的属性,那么这一过程我们成为类的派生
经典类和新式类
什么是经典类 什么事是新式类
'''
Python 2 当中类分为新式类和经典类
Python 3中全部叫新式类
python 2中如果有继承父类是object 就是新式类,继承其他类不算,但是如果继承其他类,其他类有其他了object 那就是新式类
'''
# 经典类
class 类名:
pass
# 新式类
class 类名(object):
pass
经典类的继承特点:深度优先
新式类的继承特点:广度优先
使用代码证明
class G(object):
def test(self):
print('from G')
class E(G):
def test(self):
print('from E')
class F(G):
def test(self):
print('from F')
class B(E):
def test(self):
print('from B')
class C(F):
def test(self):
print('from C')
class D(G):
def test(self):
print('from D')
class A(B,C,D):
def test(self):
print('from A')
a=A()
a.test()
print(A.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
#新式类继承顺序:A->B->E->C->F->D->G
#经典类继承顺序:A->B->E->G->C->F->D
#python3中统一都是新式类
#pyhon2中才分新式类与经典类
from A
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>)
继承原理(python如何实现的继承)python2中没有_mro_
python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如
>>> 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'>)
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类