问题出在你的装饰器上,而不是partial。部分对象应该腌制得很好:
>>> from pickle import *
>>> from functools import *
>>> f = partial(pow, 2)
>>> p = dumps(f)
>>> g = loads(p)
>>> g(5)
32
因此,您的代码的这个问题在装饰器中。它不保留原始函数的名称。试试这个:
import pickle
from functools import *
def decorator(func):
def wrapper(**kwargs):
return partial(func, **kwargs)
return wrapper
def decorated(x, y=1, z=2):
return x+y+z
dd = decorator(decorated)
y5 = dd(y=5)
pickle.dumps(y5)
使用的修改dd
应该允许泡菜逻辑通过其名称发现底层函数。这就是泡菜的工作原理。
要查看 pickle 中的函数名称,请查看转储输出:
>>> print pickle.dumps(y5)
cfunctools
partial
p0
(c__main__
decorated
p1
tp2
Rp3
(g1
(t(dp4
S'y'
p5
I5
sNtp6
b.
“decorated”这个词需要是可找到的,等于底层函数,并且不被装饰器隐藏。请记住,当函数被腌制时,只会存储它们的名称。该函数的实际内容不在泡菜中。
有一些解决方法,但它们并不漂亮。您可以使用__setstate__()来保存函数名称及其源代码。然后添加一个 __getstate__()方法来通过执行它的源来恢复函数。
或者,您可以提取函数对象对象中的字节码并保存它们。还原后,编译代码对象并执行它。
简而言之,您使用带有 @ 符号的装饰器的目标与函数酸洗的工作方式直接不一致。为了实现您的目标,您必须自定义函数酸洗以让它保存函数的功能,而不仅仅是它的名称。