我有以下情况:
# 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以及:
# 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)而不是第一个被传入。我当然可以把它包起来:
SomeClass.AddThreeNumbers = lambda self, a, b, c: A.AddThreeNumbers(a, b, c, parent=self)...but有两个缺点。首先,我失去了__doc__ (我认为这可以与functools.wraps一起使用);第二,如果更改/扩展,我必须在两个地方维护签名(参数名为a、b和c)。
有更好的办法吗?
发布于 2020-04-10 15:56:21
包装器可以只使用(self, *args, **kwargs),这样就不需要复制东西了。正如您所提到的,functools.wraps总是包装器的一个好主意。
不过,这在我看来有点难闻。AddThreeNumbers应该只关心添加三个数字;将结果设置在另一个对象上应该是其他人的责任。也许包装器应该这样做:
@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发布于 2020-04-10 22:57:34
感谢@jadkik94 94指向链接到参数和取乐的博客文章的指针,这两个第三方包似乎都能做到这一点。
下面是一个有效的示例(仅限Python 3+ ):
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 = AddThreeNumbershelp()输出看起来很完美。因此,这只是一个问题,是否值得添加对merge_args的依赖(或者复制它包含的“高级黑客”的100+行)。
更新:我后来发现在Python3(或至少3.7)下,functools.wraps实现了几乎相同的功能:
import functools
@functools.wraps(A.AddThreeNumbers)
def AddThreeNumbers( self, *pargs, **kwargs ):
kwargs[ 'parent' ] = self
return A.AddThreeNumbers( *pargs, **kwargs )
SomeClass.AddThreeNumbers = AddThreeNumbers...except表示self在help(B.SomeClass.AddThreeNumbers)输出中缺少签名,而第一个参数在help(B.SomeClass().AddThreeNumbers)输出中被吞没(因为假定它扮演了self的角色)。
https://stackoverflow.com/questions/61143739
复制相似问题