前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你知道什么是Python里的鸭子类型和猴子补丁吗?

你知道什么是Python里的鸭子类型和猴子补丁吗?

作者头像
石晓文
发布2019-08-09 18:52:14
2.5K0
发布2019-08-09 18:52:14
举报
文章被收录于专栏:小小挖掘机小小挖掘机

有时候我们会听到Python里所谓的鸭子类型猴子补丁的说法,乍一听还以为是来到了动物园,Python这只大蟒蛇还可以和鸭子和猴子一起玩耍?

非也非也,鸭子类型和猴子补丁实际上是两个生动有趣的比喻,用来说明Python的动态特性。

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

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

让我们来一探究竟吧!

一,鸭子类型

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

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

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

代码语言:javascript
复制
# 这是一个鸭子(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)

输出结果如下:

代码语言:javascript
复制
A duck named yaya is swimming...
gay ... gay ... gay ...
A goose named ee is swimming...
goo ... goo ... goo ...
代码语言:javascript
复制

二,猴子补丁

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

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

代码语言:javascript
复制
# 定义一个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)

输出结果如下:

代码语言:javascript
复制
Zzz ... Zzz ... Zzz ...
I think myself a hero and very handsome!
Earth

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

代码语言:javascript
复制
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())

输出结果如下:

代码语言:javascript
复制
280 B

这就是Python里的鸭子类型和猴子补丁的一个简单介绍,你耍明白了吗???????

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小小挖掘机 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一,鸭子类型
  • 二,猴子补丁
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档