• python面向对象(3) _三大特性


    对象的继承

    官方的说法:
    如果一个类别A“继承自”另一个类别B,就把这个A称为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。 一般静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充。
    俗语:
    子承父业,合法继承家产,就是如果你是独生子,而且你也很孝顺,不出意外,你会继承你父母所有家产,他们的所有财产都会由你使用

    继承的优点:

    1,增加了类的耦合性(耦合性不宜多,宜精)。
    2,减少了重复代码。
    3,使得代码更加规范化,合理化。

    继承的分类。

    继承:可以分单继承,多继承。
    这里需要补充一下python中类的种类(继承需要):
    在python2x版本中存在两种类.:
      ⼀个叫经典类. 在python2.2之前. ⼀直使⽤的是经典类. 经典类在基类的根如果什么都不写.
      ⼀个叫新式类. 在python2.2之后出现了新式类. 新式类的特点是基类的根是object类。
    python3x版本中只有一种类:
    python3中使⽤的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object

    执行顺序

    实例化对象时必须执行__init__方法,类中没有,从父类找,父类没有,从object类中找。
    先要执行自己类中的eat方法,自己类没有才能执行父类中的方法。
    如果想执行父类的func方法,这个方法并且子类中夜用,那么就在子类的方法中写上:
    父类.func(对象,其他参数)

    经典类的多继承

    但是经典类的MRO
    ⼴度优先遍历
    从头开始. 从左往右. ⼀条路跑到头, 然后回头. 继续⼀条路跑到头. 就是经典类的MRO算法.

    新式类的多继承

    MRO是一个有序列表L,在类被创建时就计算出来。
    通用计算公式为:
    mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )
    merge操作是C3算法的核心

    表头和表尾

    表头:
      列表的第一个元素
    表尾:
      列表中表头以外的元素集合(可以为空)
    示例
      列表:[A, B, C]
      表头是A,表尾是B和C

    列表之间的+操作

    +操作:

    [A] + [B] = [A, B]
    (以下的计算中默认省略)

    merge操作示例:
    如计算merge( [E,O], [C,E,F,O], [C] )
    有三个列表 :  ①      ②          ③
    merge不为空,取出第一个列表列表①的表头E,进行判断                              
       各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表
    取出列表②的表头C,进行判断
       C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除
       merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )
    进行下一次新的merge操作 ......
    

    封装:

    把很多数据封装到⼀个对象中. 把固定功能的代码封装到⼀个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想. 具体的情况具体分析. 比如. 你写了⼀个很⽜B的函数. 那这个也可以被称为封装. 在⾯向对象思想中. 是把⼀些看似⽆关紧要的内容组合到⼀起统⼀进⾏存储和使⽤. 这就是封装
    俗语:封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。.

    第一步:将内容封装到某处
    第二步:从某处调用被封装的内容
    调用被封装的内容时,有两种情况:
    通过对象直接调用
    通过self间接调用

    多态:

    同⼀个对象, 多种形态. 这个在python中其实是很不容易说明⽩的. 因为我们⼀直在⽤. 只是没有具体的说. 比如. 我们创建⼀个变量a = 10 , 我们知道此时a是整数类型. 但是我们可以通过程序让a = "A", 这时, a⼜变成了字符串类型. 这是我们都知道的. 但是, 我要告诉你的是. 这个就是多态性. 同⼀个变量a可以是多种形态。
    俗语:多态,同一个对象,多种形态。python默认支持多态

    # 在java或者c#定义变量或者给函数传值必须定义数据类型,否则就报错。
    
    def func(int a):
        print('a必须是数字')
        
    # 而类似于python这种弱定义类语言,a可以是任意形态(str,int,object等等)。
    def func(a):
        print('a是什么都可以')
        
    # 再比如:
    class F1:
        pass
    
    
    class S1(F1):
        
        def show(self):
            print 'S1.show'
    
    
    class S2(F1):
        
        def show(self):
            print 'S2.show'
    
    
    # 由于在Java或C#中定义函数参数时,必须指定参数的类型
    # 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
    # 而实际传入的参数是:S1对象和S2对象
    
    def Func(F1 obj):
    """Func函数需要接收一个F1类型或者F1子类的类型"""
    
        print obj.show()
        
    
    s1_obj = S1()
    Func(s1_obj)  # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show
    
    s2_obj = S2()
    Func(s2_obj)  # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
    
    Python伪代码实现Java或C  # 的多态
    

    鸭子类型

    python中有一句谚语说的好,你看起来像鸭子,那么你就是鸭子。
    对于代码上的解释其实很简答:
    class A:
        def f1(self):
            print('in A f1')
        
        def f2(self):
            print('in A f2')
    
    
    class B:
        def f1(self):
            print('in A f1')
        
        def f2(self):
            print('in A f2')
            
    obj = A()
    obj.f1()
    obj.f2()
    
    obj2 = B()
    obj2.f1()
    obj2.f2()
    # A 和 B两个类完全没有耦合性,但是在某种意义上他们却统一了一个标准。
    # 对相同的功能设定了相同的名字,这样方便开发,这两个方法就可以互成为鸭子类型。
    
    # 这样的例子比比皆是:str  tuple list 都有 index方法,这就是统一了规范。
    # str bytes 等等 这就是互称为鸭子类型。
    

    类的约束

    约束是对类的约束.
    俗语:就是给类制定规则

    对类的约束有两种:

    1. 提取⽗类. 然后在⽗类中定义好⽅法. 在这个⽅法中什么都不⽤⼲. 就抛⼀个异常就可以了. 这样所有的⼦类都必须重写这个⽅法. 否则. 访问的时候就会报错..
    2. 使⽤元类来描述⽗类. 在元类中给出⼀个抽象⽅法. 这样⼦类就不得不给出抽象⽅法的具体实现. 也可以起到约束的效果

    总结:

    约束. 其实就是⽗类对⼦类进⾏约束. ⼦类必须要写xxx⽅法. 在python中约束的⽅式和⽅法有两种:

    1. 使⽤抽象类和抽象⽅法, 由于该⽅案来源是java和c#. 所以使⽤频率还是很少的
    2. 使⽤⼈为抛出异常的⽅案. 并且尽量抛出的是NotImplementError. 这样比较专业, ⽽且错误比较明确.(推荐)

    super()深入了解

    super是严格按照类的继承顺序执行.
    super可以下一个类的其他方法
    super()严格按照类的mro顺序执行

  • 相关阅读:
    Jenkins + GitLab 通过 Webhook 自动触发构建爬坑记录
    Spring Cloud Eureka 学习记录
    [源码分析]ArrayList
    一个简单的统计问题(解决方案:Trie树)
    Redis基本数据类型命令汇总
    Redis的Pub/Sub客户端实现
    从ByteBuffer中解析整数
    学习T-io框架,从写一个Redis客户端开始
    折腾一下WebSocket的ArrayBuffer传输方式
    Ubuntu安装docker笔记
  • 原文地址:https://www.cnblogs.com/SkyRabbit/p/11317871.html
Copyright © 2020-2023  润新知