zoukankan      html  css  js  c++  java
  • 面向对象的三大特性 鸭子类型 类的约束 super的深度剖析

    1.三大特性

    封装

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

    继承

    ​ ⼦类可以⾃动拥有⽗类中除了私有属性外的其他所有内容. 说⽩了, ⼉⼦可以随便⽤爹的东⻄. 但是朋友们, ⼀定要认清楚⼀个事情. 必须先有爹, 后有⼉⼦. 顺序不能乱, 在python中实现继承非常简单. 在声明类的时候, 在类名后⾯添加⼀个⼩括号,就可以完成继承关系. 那么什么情况可以使⽤继承呢? 单纯的从代码层⾯上来看. 两个类具有相同的功能或者特征的时候. 可以采⽤继承的形式. 提取⼀个⽗类, 这个⽗类中编写着两个类相同的部分. 然后两个类分别取继承这个类就可以了. 这样写的好处是我们可以避免写很多重复的功能和代码. 如果从语义中去分析的话. 会简单很多. 如果语境中出现了x是⼀种y. 这时, y是⼀种泛化的概念. x比y更加具体. 那这时x就是y的⼦类. 比如. 猫是⼀种动物. 猫继承动物. 动物能动. 猫也能动. 这时猫在创建的时候就有了动物的"动"这个属性. 再比如, ⽩骨精是⼀个妖怪. 妖怪天⽣就有⼀个比较不好的功能叫"吃⼈", ⽩骨精⼀出⽣就知道如何"吃⼈". 此时 ⽩骨精继承妖精.

    多态

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

    2.鸭子类型

    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 等等 这就是互称为鸭子类型。

    3.类的约束

    ​ 类的约束有两种:

    第一种:抛出异常

    ​ 提取⽗类. 然后在⽗类中定义好⽅法. 在这个⽅法中什么都不⽤⼲. 就抛⼀个异常就可以了. 这样所有的⼦类都必须重写这个⽅法. 否则. 访问的时候就会报错.

    class Payment:
        def pay(self,money):
            raise Exception("子类设置pay方法")
    
    
    class QQpay(Payment):
        def pay(self,money):
            print(f"QQ支付{money}金额")
    
    class Alipay(Payment):
        def pay(self,money):
            print(f"支付宝支付{money}金额")
    
    class Wechatpay(Payment):
        def zhifu(self,money):
            print(f"微信支付{money}金额")
    
    
    def pay(obj,money):
        obj.pay(money)
    
    
    obj1 = QQpay()
    pay(obj1,100)
    
    obj2 = Alipay()
    pay(obj2,200)
    
    obj3 = Wechatpay()
    pay(obj3,300)
    
    """
    QQ支付100金额
    Traceback (most recent call last):
    支付宝支付200金额
    File "D:/pycharm demo/练习/代码练习.py", line 30, in <module>
      pay(obj3,300)
    File "D:/pycharm demo/练习/代码练习.py", line 20, in pay
      obj.pay(money)
    File "D:/pycharm demo/练习/代码练习.py", line 3, in pay
      raise Exception("子类设置pay方法")
    Exception: 子类设置pay方法
    """
    

    第二种:使用元类

    ​ 使⽤元类来描述⽗类. 在元类中给出⼀个抽象⽅法. 这样⼦类就不得不给出抽象⽅法的具体实现. 也可以起到约束的效果.

    from abc import ABCMeta,abstractmethod
    
    class Payment(metaclass=ABCMeta):
        @abstractmethod
        def pay(self,money):
            pass
    
    
    class QQpay(Payment):
        def pay(self,money):
            print(f"QQ支付{money}金额")
    
    class Alipay(Payment):
        def pay(self,money):
            print(f"支付宝支付{money}金额")
    
    class Wechatpay(Payment):
        def zhifu(self,money):
            print(f"微信支付{money}金额")
    
    
    def pay(obj,money):
        obj.pay(money)
    
    
    obj1 = QQpay()
    pay(obj1,100)
    
    obj2 = Alipay()
    pay(obj2,200)
    
    obj3 = Wechatpay()
    pay(obj3,300)
    
    """
    QQ支付100金额
    Traceback (most recent call last):
    支付宝支付200金额
    File "D:/pycharm demo/练习/代码练习.py", line 63, in <module>
      obj3 = Wechatpay()
    TypeError: Can't instantiate abstract class Wechatpay with abstract methods pay
    """
    

    4.super的深度剖析

    class A:
        def f1(self):
            print('in A f1')
        
        def f2(self):
            print('in A f2')
    
    
    class Foo(A):
        def f1(self):
            super().f2()
            print('in A Foo')
            
            
    obj = Foo()
    obj.f1()
    
    """
    'in A f2'
    'in A Foo'
    """
    super可以下一个类的其他方法
    
    class A:
        def f1(self):
            print('in A')
    
    class Foo(A):
        def f1(self):
            super().f1()
            print('in Foo')
    
    class Bar(A):
        def f1(self):
            print('in Bar')
    
    class Info(Foo,Bar):
        def f1(self):
            super().f1()
            print('in Info f1')
    
    obj = Info()
    obj.f1()
    
    '''
    in Bar
    in Foo
    in Info f1
    '''
    print(Info.mro())  # [<class '__main__.Info'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <class '__main__.A'>, <class 'object'>]
    
    super()严格按照类的mro顺序执行
    
    class A:
        def f1(self):
            print('in A')
    
    class Foo(A):
        def f1(self):
            super().f1()
            print('in Foo')
    
    class Bar(A):
        def f1(self):
            print('in Bar')
    
    class Info(Foo,Bar):
        def f1(self):
            super(Foo,self).f1()
            print('in Info f1')
    
    obj = Info()
    obj.f1()
    
    """
    in Bar
    in Info f1
    """
    
  • 相关阅读:
    JS中json对象克隆
    jhipster中图片路径打包问题(webpack)
    arcgis for javascript api 4.x 中,使用本地非 4326坐标系绘制功能实现
    spring核心之IOC
    spring基于XML的声明式事务控制
    hibernate之事务处理
    hibernate之一级缓存
    hibernate之一对多,多对一
    hibernate之HQL,Criteria与SQL
    spring的基于注解的IOC配置
  • 原文地址:https://www.cnblogs.com/beichen123/p/11316992.html
Copyright © 2011-2022 走看看