大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。
返回顶部

面向对象之继承

 

一、继承

1、什么是继承?

  继承是一种新建类的方式,在python中支持一个儿子继承多个爹

  新建的类称为子类或派生类

  父类又可以称为基类或超类

  子类会‘’遗传‘’父类的属性

2、为什么要继承?

  减少代码冗余

3、怎么用继承?

class ParentClass1:
    pass

class ParentClass2:
    pass

class Subclass1(ParentClass1):
    pass

class Subclass2(ParentClass1,ParentClass2):
    pass

print(Subclass1.__bases__)#(<class '__main__.ParentClass1'>,)
print(Subclass2.__bases__)#(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

在python2中有经典类与新式类之分

在python3中全部为新式类

 

二、寻找继承关系

1、继承是类与类之间的关系,寻找这种关系需要先抽象再继承

class OldboyPeople:
    school='oldboy'

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

class OldboyTeacher(OldboyPeople):
    def change_score(self):
        print('teacher %s is changing score'%self.name)



class OldboyStudent(OldboyPeople):
    def choose(self):
        print('student %s choose course'%self.name)

tea1=OldboyTeacher('egon',18,'male')#OldboyTeacher.__init__(...)
stu1=OldboyStudent('alex',73,'female')
print(tea1.name)#egon
print(stu1.name)#alex

 

三、基于继承属性的查找

class OldboyPeople:
    school='oldboy'

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

    def f1(self):
        print('爹的f1')

class OldboyTeacher(OldboyPeople):
    def change_score(self):
        print('teacher %s is changing score'%self.name)

tea1=OldboyTeacher('egon',18,'male')
print(tea1.__dict__)#{'name': 'egon', 'age': 18, 'sex': 'male'}
print(tea1.name)#egon
print(tea1.school)#oldboy
print(tea1.change_score)
#<bound method OldboyTeacher.change_score of <__main__.OldboyTeacher object at 0x00000236244C7A58>>
print(tea1.f1)
#<bound method OldboyPeople.f1 of <__main__.OldboyTeacher object at 0x00000271923D7A58>>



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

 

四、派生

什么是派生?

  子类定义自己新的属性,如果与父类同名,以子类自己的为准

class OldboyPeople:
    school='oldboy'

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

    def f1(self):
        print('爹的f1')


class OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level,salary):
        self.name=name
        self.age=age
        self.sex=sex

        self.level=level
        self.salary=salary

    def change_score(self):
        print('teacher %s is changing score'%self.name)

    def f1(self):
        print('儿子的f1')


tea1=OldboyTeacher('egon',18,'male',9,3.1)
tea1.f1()#儿子的f1
print(tea1.name,tea1.age,tea1.sex,tea1.level,tea1.salary)#egon 18 male 9 3.1

 

五、重用父类

  在子类派生出的新方法中重用父类

方式一:指名道姓的调用(其实与继承是没有关系的)

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 OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level,salary):
        
        OldboyPeople.__init__(self,name,age,sex)
        
        self.level=level
        self.salary=salary

    def tell_info(self):
        
        OldboyPeople.tell_info(self)
        
        print('''
        等级:%s
        薪资:%s
        '''%(self.level,self.salary))

tea1=OldboyTeacher('egon',18,'male',9,3.1)
# print(tea1.name,tea1.age,tea1.sex,tea1.level,tea1.salary)#egon 18 male 9 3.1
tea1.tell_info()
'''
        -----------个人信息-----------
        姓名:egon
        年龄:18
        性别: male
        

        等级:9
        薪资:3.1
'''

方式二:super()调用(严格依赖于继承)

super()的返回值是一个特殊的对象,该对象专门用来调用父类中的属性

在python2中,super(自己的类名,self)

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 OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level,salary):
        # OldboyPeople.__init__(self,name,age,sex)
        super().__init__(name,age,sex)

        self.level=level
        self.salary=salary

    def tell_info(self):
        # OldboyPeople.tell_info(self)
        super().tell_info()
        print('''
        等级:%s
        薪资:%s
        '''%(self.level,self.salary))

tea1=OldboyTeacher('egon',18,'male',9,3.1)
# print(tea1.name,tea1.age,tea1.sex,tea1.level,tea1.salary)#egon 18 male 9 3.1
tea1.tell_info()
'''
        -----------个人信息-----------
        姓名:egon
        年龄:18
        性别: male
        

        等级:9
        薪资:3.1
'''

 

六、经典类与新式类

1、新式类(广度优先):

  继承object的类,以及该类的子类都是新式类

  在python3中,如果一个类没有指定的父类,默认就是继承object

  所以在python3中所有的类都是新式类

2、经典类(深度优先,只有python2中才区分经典类与新式类):

  没有继承object的类,以及该类的子类都是经典类

#新式类&经典类
class Foo(object):
    pass

class Bar(Foo):
    pass

print(Foo.__bases__)#(<class 'object'>,)
print(Bar.__bases__)#(<class '__main__.Foo'>,)

 

七、在多继承背景下的属性查找

在菱形继承的背景下:查找属性

1、经典类:深度优先(没有继承object的类以及子类)

2、新式类:广度优先(继承object的类以及子类)

 

八、super()依赖继承

super()会严格按照mro列表从当前查找的位置继续往后查找

class A:
    def test(self):
        print('A.test')
        super().test()
class B:
    def test(self):
        print('from B')
class C(A,B):
    pass

c1=C()
print(C.mro())
#[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
c1.test()
#A.test
#from B

 

posted @ 2018-08-27 22:54  飞乐  阅读(183)  评论(0编辑  收藏  举报