具有部分功能的猴子补丁

Monkey patching with a partial function

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

from somepackage import SomeClass

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

SomeClass.oldmethod = newmethod

其中 objnodeSomeClass.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

我收到一个与传递的参数数量相关的错误,但它非常针对我的问题,因此粘贴它可能没有帮助...我认为该错误与 oldmethod 的调用签名有关采用两个位置参数 (obj, node),我的偏函数没有正确传递对 objnode 的引用。我尝试过不同的结构,例如:

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

很抱歉,我无法生成一个最小的工作示例。我希望也许专家会从经验中认识到这个问题,并告诉我我正在尝试的事情是否可能在 partial.

的范围内

谢谢

这是一个简单的例子:

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 将当您调用 baz.bar 时,不会为您添加 self。 (这不完全正确,但真正的原因是相当技术性的。请参阅下面链接的描述符操作方法。)调用 baz.bar(baz, 1) 会起作用。要解决此问题,您必须再次创建 foo.bar 方法:

import types

# In Python 2:
foo.bar = types.MethodType(partial(foo.bar.__func__, qux=1), None, foo)
# Method that is compatible with both Python 2 and 3:
foo.bar = types.MethodType(partial(foo.bar, qux=1), foo)
# Python 3 only:
from functools import partialmethod
foo.bar = partialmethod(foo.bar, qux=1)

baz = foo()
baz.bar(1) # Works!

另请参阅:

替换:

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

与:

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