码迷,mamicode.com
首页 > 其他好文 > 详细

继承与派生

时间:2018-03-06 13:42:32      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:通过   检查   父类   选择   speed   支持   列表   object类   image   

1 什么是继承

2 经典类与新式类

3 属性查找

4 子类重用父类的方法

5 继承的实现原理

6 子类中调用父类的方法


 

1 什么是继承

是一种新建类的方式,新建的类称为子类,子类会遗传父类的属性,可以减少代码冗余在python中,子类(派生类)可以继承一个或者多个父类(基类,超类)

class Parent1: #定义父类
    pass
class Parent2(object): #定义父类
    pass
class Sub1(Parent1): #单继承,基类是ParentClass1,派生类是SubClass
    pass
class Sub2(Parent1,Parent2): #python支持多继承,用逗号分隔开多个继承的类
    pass


print(Sub1.__bases__)#__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
print(Sub2.__bases__)
print(Parent1.__bases__)
print(Parent2.__bases__)

2 经典类与新式类

1.只有在python2中才分新式类和经典类,python3中统一都是新式类

2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类

3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类

4.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类

3 属性查找

先从自己类中查找,再然后再去父类中找...直到最顶级的父类。

#属性查找
class Foo:
    def f1(self):
        print(Foo.f1)

    def f2(self): #self=obj
        print(Foo.f2)
        self.f1() #obj.f1()

class Bar(Foo):
    def f1(self):
        print(Bar.f1)

obj=Bar()
print(obj.__dict__)
obj.f2()
‘‘‘{}
Foo.f2
Bar.f1
‘‘‘

4 子类重用父类的方法

#方法一(不建议用)
class OldboyPeople:
    school = Oldboy

    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def tell_info(self):
        print(<名字:%s 年龄:%s 性别:%s> %(self.name,self.age,self.sex))

class OldboyStudent(OldboyPeople):
    def __init__(self,name,age,sex,course,stu_id):
        OldboyPeople.__init__(self,name,age,sex)#调用父类的方法
        self.course=course
        self.stu_id=stu_id

    def learn(self):
        print(%s is learning %self.name)

    def tell_info(self):
        print(我是学生:,end=‘‘)
        # self.tell_info() #stu1.tell_info()
        OldboyPeople.tell_info(self) #调用父类的方法

stu1=OldboyStudent(牛榴弹,18,male,Python,1)
stu1.tell_info()
#方法二:使用super关键字
class OldboyPeople:
    school = Oldboy

    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def tell_info(self):
        print(<名字:%s 年龄:%s 性别:%s> %(self.name,self.age,self.sex))

class OldboyStudent(OldboyPeople):
    def __init__(self,name,age,sex,course):
        # OldboyPeople.__init__(self,name,age,sex)
        super(OldboyStudent,self).__init__(name,age,sex)#使用super关键字
        self.course=course

    def tell_info(self):
        print(我是学生: ,end=‘‘)
        # OldboyPeople.tell_info(self)
        super(OldboyStudent,self).tell_info() #使用super关键字

stu1=OldboyStudent(egon,18,male,python)
# print(stu1.name,stu1.age,stu1.sex,stu1.course)
stu1.tell_info()

5 继承的实现原理

      1、继承顺序

    技术分享图片技术分享图片

class A(object):
    def test(self):
        print(from A)

class B(A):
    def test(self):
        print(from B)

class C(A):
    def test(self):
        print(from C)

class D(B):
    def test(self):
        print(from D)

class E(C):
    def test(self):
        print(from E)

class F(D,E):
    # def test(self):
    #     print(‘from F‘)
    pass
f1=F()
f1.test()
print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性

#新式类继承顺序:F->D->B->E->C->A(广度优先)
#经典类继承顺序:F->D->B->A->E->C(深度优先)
#python3中统一都是新式类
#pyhon2中才分新式类与经典类

2、继承原理

为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类

>>> F.mro() #等同于F.__mro__
[<class __main__.F>, <class __main__.D>, <class __main__.B>, <class __main__.E>, <class __main__.C>, <class __main__.A>, <class object>
]

6 子类中调用父类的方法

#方法一:指名道姓,即父类名.父类方法()

#_*_coding:utf-8_*_

class Vehicle: #定义交通工具类
     Country=China
     def __init__(self,name,speed,load,power):
         self.name=name
         self.speed=speed
         self.load=load
         self.power=power

     def run(self):
         print(开动啦...)

class Subway(Vehicle): #地铁
    def __init__(self,name,speed,load,power,line):
        Vehicle.__init__(self,name,speed,load,power)
        self.line=line

    def run(self):
        print(地铁%s号线欢迎您 %self.line)
        Vehicle.run(self)

line13=Subway(中国地铁,180m/s,1000人/箱,,13)
line13.run()
#方法二:super()

class Vehicle: #定义交通工具类
     Country=China
     def __init__(self,name,speed,load,power):
         self.name=name
         self.speed=speed
         self.load=load
         self.power=power

     def run(self):
         print(开动啦...)

class Subway(Vehicle): #地铁
    def __init__(self,name,speed,load,power,line):
        #super(Subway,self) 就相当于实例本身 在python3中super()等同于super(Subway,self)
        super().__init__(name,speed,load,power)
        self.line=line

    def run(self):
        print(地铁%s号线欢迎您 %self.line)
        super(Subway,self).run()

class Mobike(Vehicle):#摩拜单车
    pass

line13=Subway(中国地铁,180m/s,1000人/箱,,13)
line13.run()

 

即使没有直接继承关系,super仍然会按照mro继续往后查找

#A没有继承B,但是A内super会基于C.mro()继续往后找
class A:
    def test(self):
        super().test()
class B:
    def test(self):
        print(from B)
class C(A,B):
    pass

c=C()
c.test() #打印结果:from B


print(C.mro())
#[<class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘__main__.B‘>, <class ‘object‘>]
技术分享图片
#指名道姓
class A:
    def __init__(self):
        print(A的构造方法)
class B(A):
    def __init__(self):
        print(B的构造方法)
        A.__init__(self)

class C(A):
    def __init__(self):
        print(C的构造方法)
        A.__init__(self)

class D(B,C):
    def __init__(self):
        print(D的构造方法)
        B.__init__(self)
        C.__init__(self)

f1=D() #A.__init__被重复调用
‘‘‘
D的构造方法
B的构造方法
A的构造方法
C的构造方法
A的构造方法
‘‘‘

#使用super()
class A:
    def __init__(self):
        print(A的构造方法)
class B(A):
    def __init__(self):
        print(B的构造方法)
        super(B,self).__init__()

class C(A):
    def __init__(self):
        print(C的构造方法)
        super(C,self).__init__()

class D(B,C):
    def __init__(self):
        print(D的构造方法)
        super(D,self).__init__()

f1=D() #super()会基于mro列表,往后找
‘‘‘
D的构造方法
B的构造方法
C的构造方法
A的构造方法
‘‘‘
指名道姓与super()的区别

当你使用super()函数时,Python会在MRO列表上继续搜索下一个类。只要每个重定义的方法统一使用super()并只调用它一次,那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次(注意注意注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表)

 

继承与派生

标签:通过   检查   父类   选择   speed   支持   列表   object类   image   

原文地址:https://www.cnblogs.com/snailgirl/p/8513785.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!