猴子修补python实例方法[重复]

Posted

技术标签:

【中文标题】猴子修补python实例方法[重复]【英文标题】:monkey-patching python an instance method [duplicate] 【发布时间】:2015-03-23 13:16:05 【问题描述】:

我正在尝试对类实例进行猴子修补,但不太明白如何修补类方法没有问题。

>>> class Simple(object): 
...     def make(self, arg):
...         return arg * 2
... 
>>> s = Simple()
>>> def times_four(self, arg):
...   return arg * 4
... 
>>> Simple.make = times_four
>>> s.make(10)
40

但是假设我只想在实例中替换make,那么最简单的方法是什么?

>>> def times_eight(self, arg):
...   return arg * 8
>>> s.make = ???

【问题讨论】:

可能...我不太明白该代码中发生了什么。 我的问题是“嘲笑”还是“猴子补丁”? 你能解释一下区别吗? 从技术上讲,这些术语在某种程度上是同义词。不同之处在于意图 - 模拟通常是为了测试目的而进行猴子修补,而后者在其起源上更为普遍。 【参考方案1】:

哇!

>>> import types
>>> s.make = types.MethodType(times_eight, s, Simple)
>>> s.make(10)
80

【讨论】:

【参考方案2】:

方法仅在从类(而不是从实例字典)接收时自动传递 self arg,因此您需要在那里传递一个 1-arg 函数:

s.make = lambda arg: times_eight(s, arg)

(您可以使用functools.partial 简化它。)

【讨论】:

我认为最好将对象添加到闭包lambda arg, s=s: time_eight(s, arg) 然而,这并不是真正的实例方法。正确的?这是一个 lambda 或部分,所以我不认为这真的有效。【参考方案3】:

您可以使用times_eight__get__ special method 创建一个新的实例方法:

>>> class Simple(object):
...     def make(self, arg):
...         return arg * 2
...
>>> s = Simple()
>>> def times_eight(self, arg):
...     return arg * 8
...
>>> s.make = times_eight.__get__(s, Simple)
>>> s.make(10)
80
>>> type(s.make)
<type 'instancemethod'>
>>>

【讨论】:

您的解决方案也很有效。我只是在展示如何在不导入 types.MethodType 的情况下做到这一点。 :) times_eight() 中使用super() 有效吗?

以上是关于猴子修补python实例方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

猴子在Python的另一个模块中修补一个类

一只猴子如何在 python 中修补一个函数?

Python 3:猴子补丁代码不能通过多处理重新导入

猴子修补对象会产生奇怪的结果

如何修补由 Python 数据形状中的装饰器注册的方法?

猴子补丁 Python 类