yiruia的个人博客分享 http://blog.sciencenet.cn/u/yiruia

博文

Day23 面向对象的继承

已有 188 次阅读 2020-3-23 09:37 |系统分类:科研笔记|关键词:学者

一、复习

面向对象编程

思想:角色的抽象、创建类、创建角色(实例化),操作这些实例。

面向对象的关键字:

class 类名:

    静态属性 = ‘aaa’

    def __init__(self):pass

类名.静态属性  #存储在类的命名空间里

对象=类名()  # 实例化,创造了一个self对象,执行__init__方法,返回self对象给外部

对象.属性

对象.方法 # 绑定方法


对象可以使用静态变量,类不可以使用对象里的属性

组合

组合:一个类的对象是另外一个类的属性,即什么是什么的关系

继承:什么有什么的关系,比如人有武器。

class A:
    def __init__(self):
        self.name = 'egon'
class B:
    def __init__(self):
        self.year = 2018
        self.month = 1
b=B()
a=A()
a.birth = b #只有当一个对象做了别人的属性的时候才叫做组合
print(a.birth.year)


二、初识继承

面向对象的三大特性:继承、多态、封装

什么是继承?

继承是一种创建新的类的方式,新创建的叫子类,继承的叫父类、超类、基类

特点:子类可以使用父类的属性(特征、技能)

继承是类与类之间的关系,一个类可以被多个类继承,一个类也可以继承多个父类——python类,使用__bases__方法可以获取子类继承的类。

class A:pass # 父类,基类,超类
class A(object):pass
class B:pass # 父类,基类,超类
class A_son(A,B):pass # 子类,派生类
class AB_son(A):pass
print(A_son.__bases__)
print(AB_son.__bases__)
print(A.__bases__) # python3 新式类 没有继承父类默认继承object
'''
(<class '__main__.A'>, <class '__main__.B'>)
(<class '__main__.A'>,)
(<class 'object'>,)
'''

为什么要继承?

减少代码冗余、提高重用性

新式类、经典类

  • 继承了object的类以及该类的子类,都是新式类。在python3中如果一个类没有继承任何类,则默认继承object类。因此python3中都是新式类

  • 没有继承object的类以及该类的子类,都是经典类。在python2中如果一个类没有继承任何类,不会继承object类,因此,只有篇python2中有经典类


派生类

概念:派生就是在子类继承父类的属性的基础上,派生出自己的属性。子类有不同于父类的属性,这个子类叫做派生类。通常情况下,子类和派生类是同一个概念,因为子类都是有不同于父类的属性,如果子类和父类属性相同,就没必要创建子类了。

单继承

class Animal:
    def __init__(self, name, hp, aggr):
        self.name = name
        self.hp = hp
        self.aggr = aggr

    def eat(self):
        print('吃药回血')

class Dog(Animal):
    def __init__(self, name, hp, aggr, kind):
        Animal.__init__(self, name, hp, aggr) #
        self.kind = kind    #派生属性

class Person(Animal):
    def __init__(self, name, hp, aggr, sex):
        Animal.__init__(self, name, hp, aggr)  #
        self.sex = sex  # 派生属性
jin = Dog('金老板',200,500,'teddy')
alex = Person('alex',300,50,'女')
print(jin.name)
print(alex.name)
'''
金老板
alex
'''
  • 父类中没有的属性在子类中出现叫做派生属性

  • 父类中没有方法在子类中出现叫做派生方法

  • 主要是子类的对象调用,子类中有的名字一定用子类的,子类中没有才找父类,如果父类也没有就报错

  • 如果父类子类都有的,用子类的

  • 如果既想实现新的功能,也想实现父类原本的功能,还需要在子类中再调用父类或super().__init__().

super()不需要传self了,()里面已经默认传了,super()关键字只在新式类中才有,python3中所有的类都是新式类。super()是用来解决多重继承问题的,直接用类名调用父类方法在单继承的时候没有问题,但是如果使用多继承,会涉及到查找顺序(MRO),重复调用(钻石继承)等种种问题。总之前人留下的经验就是:保持一致性。要不全部用类名调用父类,要不全部用super,不要一半一半。

  • super()也可以在类外使用

  • 如果还想用父类的,单独调用父类的

    父类名.方法名 需要自己传self

  • 正常代码中 单继承是为了减少代码的重复性

  • 继承表达的是一种子类是父类的关系


多继承

class A:
    def func(self): print('A')
class B:
    def func(self): print('B')
class C:
    def func(self): print('C')
class D(A,B,C):pass
    # def func(self):print('D')
d = D()
d.func() #A
class A:
    def func(self): print('A')
class B(A):
    def func(self): print('B')
class C(A):
    def func(self): print('C')
class D(B,C):pass
d = D()
d.func() #B
class A:
    def func(self): print('A')
class B(A):pass
    # def func(self): print('B')
class E:
    def func(self): print('E')
class C(E):
    def func(self): print('C')
class D(B,C):pass
d = D()
d.func() #A 
print(D.mro()) #把继承顺序都给出来了


  • 新式类中的继承顺序:广度优先

  • 经典类:如果你直接创建一个类在python2.7中就是经典类,深度优先

  • 在多继承中,我们子类的对象调用一个方法,默认的是就近原则,就近原则找的顺序是什么?

            经典类中 深度优先

            新式类中 广度优先

  • python2.7 新式类和经典类共有,新式类要继承object

  • python3 只有新式类 默认继承object

  • 经典类和新式类还有一个区别 mro方法只有新式类中有

  • super()只在python3中有

  • super()的本质不是直接找父类,而是调用者节点。

class A(object):
    def func(self): print('A')
class B(A):
    def func(self):
        super().func()
        print('B')
class C(A):
    def func(self):
        super().func()
        print('C')
class D(B,C):
    def func(self):
        super().func()
        print('D')
d = D()
d.func()
print(D.mro())
'''
A
C
B
D
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
'''
class A(object):
    def func(self): print('A')
class B(A):
    def func(self):
        super().func()
        print('B')
class C(A):
    def func(self):
        super().func()
        print('C')
class D(B,C):
    def func(self):
        super().func()
        print('D')
b = B()
b.func()
print(B.mro())
'''
A
B
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
'''

小节:

  • 继承:什么是什么的关系

  • 单继承:*****

            先抽象再继承,及各类之间的相同代码抽象出来,成为父类

            子类自己没有的名字,就可以使用父类的方法和属性,如果子类自己有一定先用自己的

            在类中用self的时候,一定要看清楚self指向谁

  • 多继承:***

        新式类和经典类

            多继承寻找名字的顺序:新式类广度优先,经典类深度优先

            在新式类中,有一个类名.mro()方法,查看广度优先的继承顺序

            python3中有一个super方法,根据广度优先的继承顺序查找上一个类



http://blog.sciencenet.cn/blog-3405644-1224841.html

上一篇:Day 22 面向对象
下一篇:Day25 面向对象的多态、封装、property、staticmethod、classmethod

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2020-5-28 13:28

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部