Python 中的猴子补丁

简介: Python 中的猴子补丁

猴子补丁是从 Monkey Patch 翻译过来的,最初接触时觉得这个名字非常奇怪,于是就搜索了下其名字的由来,大致有两种说法:

  1. 猴子补丁这个叫法起源于 Zope 框架,开发者在修复 ZopeBug 的时候,经常在程序后面追加更新部分。最开始大家把它叫 Guerrilla Patch(杂牌军补丁),位置不固定,哪里需要就出现在哪里。在英语里 GuerrillaGorilla 读音相似,有人就将其叫为 Gorilla PatchGorilla 译为大猩猩,叫着叫着,又有人把其叫成了 Monkey Patch 猴子补丁。
  2. 另一种说法是在英文里 monkeying about 译为顽皮的,而猴子补丁的用法会将代码弄乱,也比较 “顽皮”,故此就有了 Monkey Patch 的叫法。

什么是猴子补丁

简单介绍了猴子补丁这个词的由来,那么什么是猴子补丁呢?所谓猴子补丁就是一种运行时的属性替换。

直白了说,就是在程序运行的过程中,为内存中的对象替换属性、方法,而不是通过修改源码的方式替换对象的属性、方法等。

猴子补丁示例

Python 在 3.5 版本之前,只对协程提供了基本支持,不过有个第三方库 gevent 通过大量使用猴子补丁的方式提供了更加完善的协程支持。

gevent 使用猴子补丁方法如下:

import socket
from gevent import monkey
print(f'Python socket: {socket.socket}')
monkey.patch_socket()  # 使用 gevent 的猴子补丁
print(f'Gevent socket: {socket.socket}')

输出结果:

Python socket: <class 'socket.socket'>
Gevent socket: <class 'gevent._socket3.socket'>

gevent 使用猴子补丁非常简单,只需要一行代码 monkey.patch_socket() 就能实现。通过程序执行的结果可以发现,使用猴子补丁后,Python 内置的 socket 对象被替换为了 geventsocket 对象。这就是猴子补丁的威力。

自己实现猴子补丁

看了 gevent 中使用猴子补丁的使用示例,对猴子补丁有了一个初步的概念。接下来我们就来自己实现一个猴子补丁。

在 Python 的 multiprocessing 内置库中,有一个 cpu_count 方法可以获取当前计算机的 CPU 核心数,我们可以通过用猴子补丁的方式来修改 cpu_count 这个方法。

import multiprocessing
# 获取计算机 CPU 核心数
print(multiprocessing.cpu_count())
def cpu_count():
    return 10
multiprocessing.cpu_count = cpu_count  # 使用猴子补丁方式
print(multiprocessing.cpu_count())

输出结果:

4
10

我电脑的 CPU 核心数为 4,所以第一次输出结果即为 4。而通过 multiprocessing.cpu_count = cpu_count 这行代码将 multiprocessingcpu_count 方法替换成自己实现的 cpu_count 方法后,得到的结果则为 10。

这里就通过猴子补丁的方式实现了运行时的方法替换。这就是猴子补丁的原理,在未对源码以任何形式进行修改的情况下,只通过 打补丁 的方式替换掉 multiprocessing原有的 cpu_count 方法,以后每次调用 multiprocessing.cpu_count() 执行的都是自定义的 cpu_count 方法,也就是说返回结果将永远为 10。

总结

猴子补丁灵活且强大,但却是把双刃剑。维基百科上说,猴子补丁是一种很脏的编程技巧。它固然强大,但如果被滥用,将造成代码难以维护。

相关文章
|
6月前
|
设计模式 测试技术 Python
Python中的猴子补丁
Python中的猴子补丁
|
Python
Python经典编程习题100例:第80例:猴子分桃
Python经典编程习题100例:第80例:猴子分桃
268 0
|
Python
Python经典编程习题100例:第21例:猴子吃桃问题
Python经典编程习题100例:第21例:猴子吃桃问题
74 0
|
JSON Go 开发者
Python 中的鸭子类型和猴子补丁
Python 开发者可能都听说过鸭子类型和猴子补丁这两个词,即使没听过,也大概率写过相关的代码,只不过并不了解其背后的技术要点是这两个词而已。
156 0
|
JSON 数据格式 Ruby
说说Python中猴子补丁是什么?
公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始,每天一题。如果参考答案不够好,或者有错误的话,麻烦大家可以在留言区给出自己的意见和讨论,大家是要一起学习的 。
151 0
|
11天前
|
存储 数据挖掘 开发者
Python编程入门:从零到英雄
在这篇文章中,我们将一起踏上Python编程的奇幻之旅。无论你是编程新手,还是希望拓展技能的开发者,本教程都将为你提供一条清晰的道路,引导你从基础语法走向实际应用。通过精心设计的代码示例和练习,你将学会如何用Python解决实际问题,并准备好迎接更复杂的编程挑战。让我们一起探索这个强大的语言,开启你的编程生涯吧!
|
17天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
17天前
|
机器学习/深度学习 数据挖掘 Python
Python编程入门——从零开始构建你的第一个程序
【10月更文挑战第39天】本文将带你走进Python的世界,通过简单易懂的语言和实际的代码示例,让你快速掌握Python的基础语法。无论你是编程新手还是想学习新语言的老手,这篇文章都能为你提供有价值的信息。我们将从变量、数据类型、控制结构等基本概念入手,逐步过渡到函数、模块等高级特性,最后通过一个综合示例来巩固所学知识。让我们一起开启Python编程之旅吧!
|
17天前
|
存储 Python
Python编程入门:打造你的第一个程序
【10月更文挑战第39天】在数字时代的浪潮中,掌握编程技能如同掌握了一门新时代的语言。本文将引导你步入Python编程的奇妙世界,从零基础出发,一步步构建你的第一个程序。我们将探索编程的基本概念,通过简单示例理解变量、数据类型和控制结构,最终实现一个简单的猜数字游戏。这不仅是一段代码的旅程,更是逻辑思维和问题解决能力的锻炼之旅。准备好了吗?让我们开始吧!