我在代码
中从第三方库中获取了一个类实例i = x.get_instance()
然后我的代码从此实例调用一个方法。
i.method_a()
将在此类中调用我想要添加行为的方法。
我现在找到的唯一方法是
class BetterClass(ThirdPartyClass):
def getMessage(self):
message = super(BetterClass, self).getMessage()
... add behaviour
return message
i.__class__ = BetterClass
i.method_a()
但是添加这种行为的更好方法是什么,因为我无法改变我回来的实例。 我不是自己做的
答案 0 :(得分:1)
你可以用:
>>> class Example(object):
... def foo(self):
... print "foo"
...
>>> a=Example()
>>> a.foo()
foo
>>>
>>> def new_foo(self):
... Example.foo(self)
... print "new"
...
>>> funcType = type(Example.foo)
>>> a.foo = funcType(new_foo, a, Example)
>>> a.foo()
foo
new
此处type
是class。 funcType
是一个实例方法:
>>> funcType
<type 'instancemethod'>
>>> help(funcType)
...
class instancemethod(object)
| instancemethod(function, instance, class)
|
| Create an instance method object.
另外,(感谢@bruno desthuilliers),您可以这样做:
a.foo = new_foo.__get__(a, type(a))
而不是使用funcType
。
答案 1 :(得分:0)
如果您确定x.get_instance()
将返回ThirdPartyClass
的实例,则可以monkeypatch ThirdPartyClass
:
from thirdpartlib.module import ThirdPartyClass
def patch_ThirdPartyClass():
_get_message = ThirdPartyClass.get_message
def get_message(self):
message = _get_message()
# add behaviour here
return message
ThirdPartyClass.get_message = get_message
patch_ThirdPartyClass()
您只是想确保每个进程只执行一次此代码 - 如果您不确定是否可以保证这一点,那么最好添加一些标记:
def patch_ThirdPartyClass():
_get_message = ThirdPartyClass.get_message
if getattr(_get_message, "patched", False):
return
def get_message(self):
message = _get_message()
# add behaviour here
return message
get_message.patched = True
ThirdPartyClass.get_message = get_message
patch_ThirdPartyClass()
此外,您还要确保在对x.get_instance()
进行任何调用之前执行此代码。
如果由于任何原因您无法使用上述解决方案,您仍然可以基于每个实例对该方法进行monkeypatch:
def patch_instance(instance):
_get_message = instance.get_message
def get_message(self):
message = _get_message()
# add behaviour here
return message
instance.get_message = get_message.__get__(instance, type(instance))
return instance
i = patch_instance(x.get_instance())
相同的考虑适用于wrt /确保您只应用此修补程序一次,因此您可能希望添加类似的标记内容并在类monkeypatch版本中进行测试。
作为最后一点:如果您必须回退到patch_instance
解决方案,并希望确保所有调用x.get_instance()
,则返回已修补的实例,您可能还需要修补x.get_instance
以便调用patch_instance
。
答案 2 :(得分:0)
假设你有一个类Foo,它有一个bar方法:
>>> class Foo(object):
... def __init__(self, name):
... self.name = name
... def bar(self):
... print "bar", self.name
如果您创建此类的实例名为foo
...
>>> foo = Foo('eggs')
>>> foo.bar()
bar eggs
...然后你要修补bar方法。首先定义一个函数:
>>> def bar(self):
... self.__class__.bar(self) # you can call the original method
... print "spam", self.name
您可以在不修补类的情况下修补实例:
>>> import types
>>> foo.bar = types.MethodType(bar, foo, Foo)
>>> foo.bar()
bar eggs
spam eggs
不确定这是否正确(可能不是一个好主意),但它确实有效。
原始课程完好无损:
>>> otherfoo = Foo('foo')
>>> otherfoo.bar()
bar foo