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.如果对下一个类存在两个合法的选择,选择第一个父类

原文地址:https://www.cnblogs.com/plf-Jack/p/11052958.html