面对对象编程之三大特性之继承

一,继承的介绍

1,什么是继承

       继承一种新建类方式,新建的类称之为子类/派生类,被继承的类称之为父类\基类\超类

python中继承的特点:

    1,子类可以遗传/重用父类的属性

    2,python中一个子类可以同时继承多个父类

    3,在继承背景下去说,python中的类分为两种:新式类和经典类

         新式类:但凡继承了object的类foo,以及该类的子集.....都是新式类

        在python3中一个类即便是没有显示的继承任何类,默认就会继承object

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

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

        在python2中才区分新式类和经典类

        在python中一个类如果没有显示地继承任何类,也不会继承object

2,为何要用继承

        减少类与类之间代码冗余

3,如何用继承

class Parent1(object):
        pass

class Parent2(object):
        pass

class Sub1(object):
        pass

class Sub2(Parent1,Parent2):
        pass

print(Parent1.__bases__)

print(Parent2.__base__)      

print(Sub1.__base__)   

print(Sub2.__base__)   

输出是:

(<class 'object'>,)
(<class 'object'>,)
(<class '__main__.Parent1'>,)
(<class '__main__.Parent1'>, <class '__main__.Parent2'>)

这时产生的问题:

1,子类如何重用父类的属性

2,在继承背景下,属性查找的优先级

3,新式类与经典类在属性查找上的区别

二,利用继承来解决类与类之间代码冗余问题

class OldboyPeople:

     school = 'Oldboy'

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

         self.name = name

         self.age = age

         self.sex = sex

class OldboyStudent(OldboyPeople)

        def choose_course(self):
                print("%s choosing course" %self.name)

class OldboyTeacher(OldboyPeople):

        def score(self,stu,num):

                stu.score = num

stu1 = OldboyStudent('老王',38,'male')

print(stu1.__dict__)

tea1 = OldboyTeacher('张老师',25,'female')

print(tea1.__dict__)

输出是:

{'name': '老王', 'age': 38, 'sex': 'male'}
{'name': '张老师', 'age': 25, 'sex': 'female'}

可以直接调用父类里面的__init_函数给学生和老师对象传值

可是,这样对象就不能有独特的特征,所以要在子集下面再定义一个__init__函数

三,在子类派生的新方法中重用父类功能的方式一

指名道姓的引用某一类中的函数

总结:

1,与继承无关

2,访问时类的函数,没有自动传值的效果

class OldboyPeople:

     school = 'Oldboy'

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

         self.name = name

         self.age = age

         self.sex = sex

class OldboyStudent(OldboyPeople)

        def __init__(self,name,age,sex,score = 0):

             OldboyPeople.__init__(self,name,age,sex)

            self.score = score

        def choose_course(self):
                print("%s choosing course" %self.name)

class OldboyTeacher(OldboyPeople):

        def __init__(self,name,age,sex,level):
             OldboyPeople.__init__(self,name,age,sex)

             self.level = level

        def score(self,stu,num):

                stu.score = num

stu1 = OldboyStudent('老王',38,'male',80)

print(stu1.__dict__)

tea1 = OldboyTeacher('张老师',25,'famale',10)

print(tea1__dict__)

{'name': '老王', 'age': 38, 'sex': 'male', 'score': 80}
{'name': '张老师', 'age': 25, 'sex': 'female', 'level': 10}

总结,这样可以直接调用父类的函数,和继承无关也按照类名可以直接查找

四,在单继承背景下的属性查找

1,查找的优先级:对象>>对象的类>>父类>>父类

class Foo():

       x = 4     #第四查找

class Bar1(Foo):
      x = 3     #第三查找

class Bar2(Bar1):
      x = 2     # 第二查找

obj = Bar2()

obj.x = 1    # 第一查找

print(obj.x)

例题:

class Foo:

        def  f1(self):

             print('Foo.f1')

        def  f1(self):

             print('Foo.f2')

             self.f1()

class Bar(Foo):

        def f1(self):

             print('Bar.f1')

obj = Bar()

obj.f2()

输出为:
Foo.f2
Bar.f1

它只要遇到self查值都会按照:对象>>对象的类>>父类>>父类顺序查找

五,在多继承背景下的属性查找

1,优先级:如果一个子类继承多个分支(多个分支没有共同继承一个非object的类)

此时属性的查找优先级是:对象>>对象的类>>按照从左往右的顺序一个分支一个分支的找下去

2,菱形的继承问题:

新式类:广度有限查找,从左往右一个分支一个分支的查找,在最后一个分支才去查找顶级类

经典类:深度有限查找,从左往右一个分支有个分支的查找,在第一个分支就查找顶级类

第四层:

class G:

        x = 'G'

第三层:

class E(G):

        x = 'E'

class F:

        x = 'F'

第二层:

class B(E):

        x = 'B'

class C(F):

        x = 'C'

class D:

        x = 'D'

第一层:

class A(B,C,D):

        x = 'A'

obj = A()

obj.x = 1

print(obj.x)

新式类(广度优先):obj>>A>>B>>E>>C>>F>>D>>G>>object

经典类(深度优先):obj>>A>>B>>E>>G>>C>>F>>D

python专门为新式类内置了一个mro的方法,用来查看c3算法的计算结果,

print(A.mro())   # 也就是新式类查找名称的顺序

六,在子类派生的新方法中重用父类功能的方式二:

super()必须在类中用

1,在python2中:supper(自己的类名,自己的对象)

2,在python3中:supper()

调用函数会得到一个特殊的对象,应该专门用来访问父类中的属性,强调的是:完全参照mro列表!!!

总结:

1,严格依赖继承的mro列表

2,访问是绑定方法,有自动传值的效果

class OldboyPeople:
    school = 'Oldboy'

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

class OldboyStudent(OldboyPeople):
    def __init__(self, name, age, sex, score=0):
        super(OldboyStudent,self).__init__(name,age,sex)   #  supper在python2中的用法
        self.score = score

    def choose_course(self):
        print('%s choosing course' % self.name)

class OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level):
        super().__init__(name,age,sex)      # supper在python3中的用法
        self.level=level

    def score(self,stu,num):
        stu.score=num


stu1=OldboyStudent("老王"'',38,'male')
print(stu1.__dict__)

tea1=OldboyTeacher('张老师',25,'female',10)
print(tea1.__dict__)

输出是:

{'name': '老王', 'age': 38, 'sex': 'male', 'score': 0}
{'name': '张老师', 'age': 25, 'sex': 'female', 'level': 10}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值