• 猴子补丁


      0 猴子补丁 - Monkey Patching

    1
    定义, 2 猴子补丁(monkey patching) 3    在运行时动态修改模块、类或函数,通常是添加功能或修正缺陷。猴子补丁在代码运行时 4 (内存中)发挥作用,不会修改源码,因此只对当前运行的程序实例有效。 5 因为猴子补丁破坏了封装,而且容易导致程序与补丁代码的实现细节紧密耦合, 6 所以被视为临时的变通方案,不是集成代码的推荐方式。 7 8 monkey patching 9 Dynamically changing a module, class or function at run time, 10 usually to add features or fix bugs. Because it is done in memory 11 and not by changing the source code, a monkey patch only affects the 12 currently running instance of the program. Monkey patches break 13 encapsulation and tend to be tightly coupled to the implementation 14 details of the patched code units, so they are seen as temporary 15 work-arounds and not a recommended technique for code integration. 16 17 18 猴子补丁的名声不太好。如果滥用,会导致系统难以理解和维护。补丁通常与目标紧密耦合, 19 因此很脆弱。另一个问题是,打了猴子补丁的两个库可能相互牵绊,因为第二个库可能撤销 20 了第一个库的补丁。不过猴子补丁也有它的作用,例如可以在运行时让类实现协议。 21 适配器设计模式通过实现全新的类解决这种问题。为 Python 打猴子补丁不难,但是有些局限。 22 与 Ruby 和 JavaScript 不同, Python 不允许为内置类型打猴子补丁。 23 其实这是优点,因为这样可以确保 str 对象的方法始终是那些。 24 这一局限能减少外部库打的补丁有冲突的概率。 25 26 看例子之前, 回顾一下儿 协议 protocol, 27 详见 duck typing 一文, 28 http://www.cnblogs.com/zzyzz/p/7723272.html 29 在 Python 中创建功能完善的序列类型无需使用继承, 只需实现符合序列协议的方法. 30 在面向对象编程中,协议是非正式的接口,只在文档中定义,在代码中不定义. 31 例如,Python 的序列协议只需要 __len____getitem__ 两个方法. 32 任对象/类型(A)只要使用标准的签名和语义实现了这两个方法,就能用在任何期待序列的地方, 33 然而A 是不是哪个类的子类无关紧要,只要提供了所需的方法即可.这就是 python 序列协议. 34 协议是非正式的,没有强制力,因此如果你知道类的具体使用场景,通常只需要实现一个协议的部分. 35 例如,为了支持迭代,只需实现 __getitem__ 方法,没必要提供 __len__方法. 36 37 例子, 38 注意 '>>>' 表示在交互式控制台 console 的输入 39 >>>class ballgame(object): # 这个class 可以生成一个 ball 的组合集合. 40 ... colors = ['red','green','bule'] 41 ... boxs = ['1', '2', '3'] 42 43 ... def __init__(self): 44 ... self.ballsets = [(b, c) for b in self.boxs for c in self.colors] 45 46 ... def __getitem__(self, position): 47 ... return self.ballsets[position] 48 49 ... def __len__(self): 50 ... return len(self.ballsets) 51 52 # def __setitem__(self, key, value): 53 # self.ballsets[key] = value 54 ... def pickone(self,position): 55 ... return self.ballsets[position] 56 57 >>>ball = ballgame() 58 >>>ball.ballsets 59 [('1', 'red'), ('1', 'green'), ('1', 'bule'), ('2', 'red'), ('2', 'green'), 60 ('2', 'bule'), ('3', 'red'), ('3', 'green'), ('3', 'bule')] 61 >>>ball.pickone(2) 62 ('1', 'bule') # 这里会发现主要取得位置相同, 取出的 ball 组合就不变. 63 # 我们是通过 random 模块重新排序 ball 示例中 ball 组合的顺序. 64 >>>import random 65 >>>random.shuffle(ball) 66 Traceback (most recent call last): 67 File "<input>", line 1, in <module> 68 File "C:Usersyzzhou8AppDataLocalProgramsPythonPython36-32lib andom.py", line 274, in shuffle 69 x[i], x[j] = x[j], x[i] 70 TypeError: 'ballgame' object does not support item assignment 71 72 #发现 random.shuffle 不可行,原因是 ballgame 类中没有实现可变序列协议的 __setitem__ 方法, 73 #当然可以通过在类中实现 __setitem__ 特殊方法后,重新初始化实例解决这个问题, 74 #现在看看如果通过 monkey patching 解决这个问题. 75 76 >>>def setballset(ballgame,position,ballset): 77 ... ballgame.ballsets[position] = ballset 78 79 >>>ball.__setitem__ = setballset 80 >>>random.shuffle(ball) 81 >>>ball.ballsets 82 [('1', 'bule'), ('1', 'green'), ('2', 'bule'), ('3', 'green'), ('2', 'green'), 83 ('2', 'red'), ('1', 'red'), ('3', 'red'), ('3', 'bule')] 84 >>>random.shuffle(ball) 85 ball.ballsets 86 [('1', 'green'), ('3', 'red'), ('3', 'green'), ('1', 'red'), ('2', 'green'), 87 ('3', 'bule'), ('2', 'red'), ('2', 'bule'), ('1', 'bule')] 88 89 # 通过 monkey patching 在 ballgame 类的实例 ball 中 实现了 __setitem__ 特殊方法, 90 # 使 ball 实例变成一个符合可变序列协议的的实例,进而使我们可以通过 random.shuffle(ball) 91 # 来重新排序 ball.ballsets 92 93 >>>ball2 = ballgame() 94 >>>random.shuffle(ball2) 95 Traceback (most recent call last): 96 File "<input>", line 1, in <module> 97 File "C:Usersyzzhou8AppDataLocalProgramsPythonPython36-32lib andom.py", line 274, in shuffle 98 x[i], x[j] = x[j], x[i] 99 TypeError: 'ballgame' object does not support item assignment 100 101 # Monkey patching 并没有在原来类中起作用. 102 103 summarize, Monkey patching 之所以起作用, 要得益于 duck typing, 104 然而, 最终要归功于 python 的 协议protocol 这一架构设计.
  • 相关阅读:
    Leetcode 515. Find Largest Value in Each Tree Row
    Paypal2017实习生-软件开发-B卷
    Codeblocks 遇到的问题 Cannot open output file, permission denied
    itoa()函数和atoi()函数详解
    Windows下如何更新 CodeBlocks 中的 MinGW 使其支持新版本 C++
    Leetcode 179. Largest Number
    合并两个有序数组到其中一个数组中
    腾讯2017实习生招聘软件开发编程题
    [LeetCode] 56
    360笔试
  • 原文地址:https://www.cnblogs.com/zzyzz/p/7728249.html
Copyright © 2020-2023  润新知