【问题标题】:Monkey patching with a partial function [duplicate]使用部分函数进行猴子修补[重复]
【发布时间】:2015-03-26 22:40:21
【问题描述】:

我正在尝试从导入的包中对 SomeClass 上的方法进行猴子补丁:

from somepackage import SomeClass

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

SomeClass.oldmethod = newmethod

其中objnodeSomeClass.oldmethod 的默认调用签名中:

class SomeClass(object):

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

我知道猴子补丁不是一个好的做法,但我们需要一种解决方法,同时解决一些无法解决的问题。上述方法工作正常,但我们想使用部分函数来做到这一点。例如:

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 的范围内。

谢谢

【问题讨论】:

  • 请至少说明您遇到的错误的文本,然后@Philips 的回答是否指向正确的方向,或者还有其他问题,您会很清楚。可能性是无穷无尽的......
  • 你的问题确实是functools.partial on class method的重复;我现在让你支付赏金。
  • 我4个月前问过这个问题,我真的没有环境来测试解决方案了。提供的答案似乎不错。虽然我没有提出赏金
  • @MartijnPieters 这是我的赏金。我没有在 classmethod 问题上找到 functools.partial,但它看起来也很相关。
  • @MartijnPieters 另外,有趣的是,这个问题实际上比那个问题更早,尽管直到今天它还没有任何答案!

标签: python partials monkeypatching


【解决方案1】:

这是一个简单的例子:

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 不会在您调用时为您添加 self baz.bar。 (这并不完全正确,但真正的原因是相当技术性的。请参阅下面链接的描述符操作方法。)调用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!

另见:

【讨论】:

  • 在 Python 3 中,使用functools.partialmethod();它是专门为这个用例设计的。
  • 谢谢,我添加了这个和另一个问题的链接。
【解决方案2】:

替换:

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

与:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 2015-03-23
    • 1970-01-01
    相关资源
    最近更新 更多