zoukankan      html  css  js  c++  java
  • 鸭子类型和猴子补丁

    一,鸭子类型

    鸭子类型是对Python中数据类型本质上是由属性和行为来定义的一种解读。

    Python是一种动态语言,不像Java和C++这种强类型语言,Python里实际上没有严格的类型检查。

    只要某个对象具有鸭子的方法,可以像鸭子那样走路和嘎嘎叫,那么它就可以被其它函数当做鸭子一样调用。

    # 这是一个鸭子(Duck)类
    class Duck:
        def __init__(self,name):
            self.name = name
        def swim(self):
            print("A duck named " + self.name+" is swimming...")
        def call(self):
            print("gay...gay...gay...")
    
    # 这是一个鹅(Goose)类
    class Goose:
        def __init__(self,name):
            self.name = name
        def swim(self):
            print("A goose named " + self.name+" is swimming...")
        def call(self):
            print("goo...goo...goo...")
    
    # duckshow这个函数设计的本意是需要传入一个Duck对象作为参数的。 
    def duckshow(duck):
        duck.swim()
        duck.call()
    
    yaya = Duck("yaya")
    ee = Goose("ee")
    
    # 但由于Python是动态语言,其数据类型属于鸭子类型,没有严格类型检查,
    # Goose这个类具有和Duck这个类相同的方法,
    # ee这只鹅划起水来像只鸭子,叫起来也像一只鸭子,
    # 所以duckshow这个函数也可以对ee进行作用。
    
    duckshow(yaya)
    duckshow(ee)

    输出结果如下:

    A duck named yaya is swimming...gay ... gay ... gay ...A goose named ee is swimming...goo ... goo ... goo ...

    二,猴子补丁(可参考monkey.patch_all)

    猴子补丁是对Python中模块和类可以在外部被动态修改这种特性的一个比喻。

    为什么叫做猴子补丁呢?在模块和类的外部对模块和类进行修改是一种非常耍赖的做法,会破坏代码的封装结构,这种事情大概只有淘气的猴子喜欢去做,因此形象地称之为猴子补丁。

    # 定义一个Dog类
    class Dog:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def sleep(self):
            print("Zzz...Zzz..Zzz...")
    
    # 在类的外部给Dog这个类添加猴子补丁
    def speak(self):
        print("I think myself a hero and very handsome!")
    
    Dog.speak = speak
    Dog.home = "Earth"
    
    # 与类的内部定义的属性和方法无差异
    snoopy = Dog("snoopy",3)
    snoopy.sleep()
    snoopy.speak()
    print(snoopy.home)
    
    

    输出结果如下:

    Zzz ... Zzz ... Zzz ...I think myself a hero and very handsome!Earth

    对于库中已经定义好的类,给它们添加猴子补丁有时候会非常方便,相当于可以自由地在外面做扩展,又不用修改源文件。

    import numpy as np
    import pandas as pd
    
    df = pd.DataFrame(np.random.randint(1,10,size=(5,5)),
                      columns = list("abcde"))
    #df.info()
    #DataFrame自带方法info打印信息太多,展示不直观。
    #给DataFrame定义一个猴子补丁方法memory简洁展示其内存消耗。
    
    def memory(self):
        mem = self.__sizeof__()
        if mem<1024:
            return("%s B"%mem)
        elif mem<1024*1024:
            return("%s KB"%mem/1024)
        elif mem<1024**3:
            return("%s MB"%mem/1024**2)
        else:
            return("%s GB"%mem/1024**3) 
    
    pd.DataFrame.memory = memory
    
    print(df.memory())

    输出结果如下:

    280 B
  • 相关阅读:
    CSS基础
    数据库优化之SQL Server
    压力测试与系统调优
    JBoss架构分析
    JBoss基本配置
    深入了解硬盘结构
    EJB2与EJB3架构对比
    JBoss高级配置
    病毒分类及病毒命名规则详解
    深入讲解防火墙的概念原理与实现
  • 原文地址:https://www.cnblogs.com/tjp40922/p/11392706.html
Copyright © 2011-2022 走看看