假设我有以下函数,它具有一个属性,用于标记回调子系统中的特殊处理:
def my_func(msg):
print msg
my_func.my_marker = SPECIAL_CONSTANT
问题在于,如果其他位代码用my_func
或其他装饰器包裹functools.partial
,那么my_marker
将会丢失。
my_partial = partial(my_func, 'hello world')
print my_partial.my_marker
>>> AttributeError...
有没有办法在包装时保护函数的属性?有没有更好的方法来存储我当前存储在my_marker
中的元数据?似乎存储对原始函数的引用也会遇到同样的问题。
答案 0 :(得分:2)
如果您知道您使用的部分内容实际上是部分内容,则可以使用它的func
属性。
电子。克。
from functools import partial
SPECIAL_CONSTANT = 'bam'
def my_func(msg):
print msg
my_func.my_marker = SPECIAL_CONSTANT
my_partial = partial(my_func, 'hello world')
print my_partial.func.my_marker
如果你真的需要处理meta_data,也许这是一种更好的方法来编写类并覆盖__call__()
方法。
答案 1 :(得分:0)
这是另一种解决方案,使用functools.update_wrapper
。
from functools import partial, update_wrapper, WRAPPER_ASSIGNMENTS
SPECIAL_CONSTANT = 'bam'
def my_func(msg):
print msg
my_func.my_marker = SPECIAL_CONSTANT
my_partial = partial(my_func, 'hello world')
update_wrapper(my_partial, my_func, WRAPPER_ASSIGNMENTS + ('my_marker', ))
print my_partial.my_marker
答案 2 :(得分:0)
受到善意评论的启发,cbo的答案和source code:
from functools import partial as _partial, update_wrapper
def partial(func, *args, **keywords):
return update_wrapper(_partial(func, *args, **keywords), func)
显示它正常工作的示例,并提出警告:
def my_func(msg):
print msg
my_func.my_marker = 'FOO'
my_partial = partial(my_func, 'hello world')
print my_func.my_marker
print my_partial.my_marker
# check other stuff is still there
print my_partial.func
print my_partial.args
print my_partial.keywords
# this works fine for READ ONLY stuff.
# so just remember:
my_partial.my_marker = 'BAR' # this _only_ updates partial, not the original
print my_func.my_marker
print my_partial.my_marker
my_func.my_marker = 'BAZ' # this _only_ updates original, not the partial
print my_func.my_marker
print my_partial.my_marker
您可以执行以下操作:
import functools
setattr(functools, 'partial', partial) # from above code
然而,这可能是一个坏主意,因为(1)它需要在任何依赖它的代码之前导入,(2)它可能破坏导入的代码,(3)它可能混淆未来的人和(4)替代方案,保持在当地,很容易。只有在你想强制第三方代码运行你的版本时才这样做。