首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将函数绑定为在第一位置以外的位置接收“自我”的方法

将函数绑定为在第一位置以外的位置接收“自我”的方法
EN

Stack Overflow用户
提问于 2020-04-10 15:43:00
回答 2查看 53关注 0票数 0

我有以下情况:

代码语言:javascript
复制
# Module A.py

def AddThreeNumbers(a, b, c, parent=None):
    """
    Add `a + b + c` and return the result.

    If `parent` is supplied, additionally store
    the result in `parent.result`.

    `parent` is optional, so we don't want it
    to be the first argument when this is
    called as a global function.
    """

    result = a + b + c
    if parent:
        parent.result = result
    return result

以及:

代码语言:javascript
复制
# Module B.py

class SomeClass:
    # ... various methods
    pass

try:
    import A
except ImportError:
    # The `A` module may or may not be available.
    pass # If it isn't, no harm no foul, but...
else:
    # if module `A` *is* available, then we would
    # like to monkey-patch the `SomeClass` class
    # so that it has an `AddThreeNumbers` method...

    SomeClass.AddThreeNumbers = XXX( A.AddThreeNumbers )

最后一行的XXX是缺少的部分。我想以某种方式转换AddThreeNumbers函数,这样self将作为最后一个参数(parent)而不是第一个被传入。我当然可以把它包起来:

代码语言:javascript
复制
SomeClass.AddThreeNumbers = lambda self, a, b, c: A.AddThreeNumbers(a, b, c, parent=self)

...but有两个缺点。首先,我失去了__doc__ (我认为这可以与functools.wraps一起使用);第二,如果更改/扩展,我必须在两个地方维护签名(参数名为abc)。

有更好的办法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-10 15:56:21

包装器可以只使用(self, *args, **kwargs),这样就不需要复制东西了。正如您所提到的,functools.wraps总是包装器的一个好主意。

不过,这在我看来有点难闻。AddThreeNumbers应该只关心添加三个数字;将结果设置在另一个对象上应该是其他人的责任。也许包装器应该这样做:

代码语言:javascript
复制
@functools.wraps(A.AddThreeNumbers)
def add_three_numbers_wrapper(self, *args, **kwargs):
    self.result = A.AddThreeNumbers(*args, **kwargs)
    return self.result

SomeClass.AddThreeNumbers = add_three_numbers_wrapper
票数 2
EN

Stack Overflow用户

发布于 2020-04-10 22:57:34

感谢@jadkik94 94指向链接到参数取乐的博客文章的指针,这两个第三方包似乎都能做到这一点。

下面是一个有效的示例(仅限Python 3+ ):

代码语言:javascript
复制
from merge_args import merge_args
@merge_args(A.AddThreeNumbers)
def AddThreeNumbers( self, *pargs, **kwargs ):
    kwargs[ 'parent' ] = self
    return A.AddThreeNumbers( *pargs, **kwargs )
SomeClass.AddThreeNumbers = AddThreeNumbers

help()输出看起来很完美。因此,这只是一个问题,是否值得添加对merge_args的依赖(或者复制它包含的“高级黑客”的100+行)。

更新:我后来发现在Python3(或至少3.7)下,functools.wraps实现了几乎相同的功能:

代码语言:javascript
复制
import functools
@functools.wraps(A.AddThreeNumbers)
def AddThreeNumbers( self, *pargs, **kwargs ):
    kwargs[ 'parent' ] = self
    return A.AddThreeNumbers( *pargs, **kwargs )
SomeClass.AddThreeNumbers = AddThreeNumbers

...except表示selfhelp(B.SomeClass.AddThreeNumbers)输出中缺少签名,而第一个参数在help(B.SomeClass().AddThreeNumbers)输出中被吞没(因为假定它扮演了self的角色)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61143739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档