猴子修补与部分功能

时间:2015-01-28 05:34:13

标签: python partials monkeypatching

我试图从导入的包中对SomeClass上的方法进行monkeypatch:

from somepackage import SomeClass

def newmethod(obj, node, **kwargs):
    """ """

SomeClass.oldmethod = newmethod

objnode位于SomeClass.oldmethod的默认呼叫签名中的位置:

class SomeClass(object):

    def oldmethod(obj, node):
        """ """  

我知道monkeypatching不是一个好习惯,但我们需要一个解决方法,同时我们解决一些本来无法解决的问题。上述方法有效,但我们希望使用部分函数来完成此操作。例如:

from functools import partial
newmethod_a = partial(newmethod, foo='a')
newmethod_b = partial(newmethod, foo='b')

正在调用部分函数,​​因为我们需要传递不同的** kwargs。但是当我现在尝试超载时:

SomeClass.oldmethod = newmethod_a

我收到与传递的参数数量相关的错误,但它对我的问题非常具体,所以粘贴它可能没有帮助......我认为错误与{{1的调用签名有关取两个位置参数(oldmethod),我的部分函数没有正确地传递对obj, nodeobj的引用。我尝试了不同的结构,如:

node

对不起,我无法提供最小的工作示例。我希望也许专家会从经验中认识到这个问题,并告诉我在newmethod_a = partial(SomeClass.newmethod, foo='a') 范围内我是否有可能尝试的是什么。

由于

2 个答案:

答案 0 :(得分:12)

这是一个简单的例子:

from functools import partial

class foo(object):
    def bar(self, pos1, **kwargs):
        print("bar got self=%r, pos1=%r, kwargs=%r" % (self, pos1, kwargs))

foo.bar = partial(foo.bar, qux=1)
baz = foo()
baz.bar(1) # Fails...

这失败了TypeError。原因是baz.bar是一个绑定方法,它希望它的第一个参数是foo实例,但partial对象不是,因此Python不会添加{{ 1}}给你打电话self。 (这不完全正确,但真正的原因是非常技术性的。请参阅下面描述的描述符方法。)调用baz.bar将起作用。要解决此问题,您必须再次baz.bar(baz, 1)方法:

foo.bar

另见:

答案 1 :(得分:1)

替换:

newmethod_a = functools.partial(newmethod, foo='a')

使用:

def newmethod_a(obj, node, **kwargs):
    kwargs.update({"foo": "a"})
    return newmethod(obj, node, **kwargs)