MyClass
在module.py
中定义。我们无法修改它。但我们知道Class定义如下所示:
class MyClass:
def method(self, msg):
print 'from method:', msg
我通过导入模块然后声明一个对象的实例来启动我的脚本:
import module
foo = module.MyClass()
然后我编写自己的函数:
def function(msg):
print 'from function:', msg
现在,每次使用foo.method('')
时,我都想调用function()
,因此它也会打印相同的消息。
这种情况会被称为monkey patching
吗?如何实现所需?
答案 0 :(得分:3)
是的,它被称为猴子修补。
这基本上是装饰,但是在已经定义了类之后手动完成。
from functools import wraps
def wrapper(f):
@wraps(f)
def wrapped(*args, **kwargs):
myFunction()
return f(*args, **kwargs)
return wrapped
MyClass.printThis = wrapper(MyClass.printThis)
它将影响MyClass
的所有实例,甚至是那些在应用修补程序之前创建的实例。
如果您不需要动态修改运行时行为,请避免使用猴子修补和更喜欢使用继承来自定义行为,如评论中所示。它不那么hacky。
答案 1 :(得分:1)
您也可以将其子类化:
class MyClass:
def method(self, msg):
print 'from method:', msg
def function(msg):
print 'from function:', msg
class MyNewClass(MyClass):
def method(self, msg):
function(msg)
MyClass.method(self, msg)
并使用它:
>>> a = MyNewClass()
>>> a.method("test")
from function: test
from method: test
或者,如果你想让你的课成为一个“新风格”的课程(对于Python 2 - 通过你的打印陈述判断) - 只需MyClass
继承object
然后你就可以使用super
:
class MyClass(object): # object added here
def method(self, msg):
print 'from method:', msg
def function(msg):
print 'from function:', msg
class MyNewClass(MyClass):
def method(self, msg):
function(msg)
super(self.__class__, self).method(msg) # super added here
答案 2 :(得分:1)
这是wim's answer的替代方案,也涉及猴子修补。但是,它通过unittest.mock
提供的功能来实现。这种方法的优点是上下文管理器用于在有限的范围内自动应用和删除补丁:
from unittest import mock
# This class would be defined in some third-party library
class MyClass:
def method(self, msg):
print('from method:', msg)
def function(msg):
print('from function:', msg)
old_method = MyClass.method
def new_method(self, msg):
old_method(self, msg)
function(msg)
# The patch is only applied within this scope
with mock.patch.object(MyClass, 'method', new_method):
foo = MyClass()
foo.method('message with patched')
# By this point MyClass is "back to normal"
print('---')
foo.method('message with original')
<强>输出强>
from method: message with patched
from function: message with patched
---
from method: message with original
答案 3 :(得分:-1)
结束这个解决方案,直到有更好的发布...
class MyClass:
def method(self, msg):
print 'from method:', msg
def function(msg, callback):
print 'from function:', msg
callback(msg)
foo = MyClass()
foo.function = function
foo.function(msg='message', callback=foo.method)