我一直在尝试 pickle 一个包含对静态类方法的引用的对象。
Pickle 失败(例如在 module.MyClass.foo
上)说明它不能被 pickle,因为 module.foo
不存在。
我提出了以下解决方案,使用包装器对象在调用时定位函数,保存容器类和函数名称:
class PicklableStaticMethod(object):
"""Picklable version of a static method.
Typical usage:
class MyClass:
@staticmethod
def doit():
print "done"
# This cannot be pickled:
non_picklable = MyClass.doit
# This can be pickled:
picklable = PicklableStaticMethod(MyClass.doit, MyClass)
"""
def __init__(self, func, parent_class):
self.func_name = func.func_name
self.parent_class = parent_class
def __call__(self, *args, **kwargs):
func = getattr(self.parent_class, self.func_name)
return func(*args, **kwargs)
不过我想知道,是否有更好的、更标准的方法来 pickle 这样的对象?
我不想更改全局 pickle
进程(例如使用 copy_reg
),但以下模式会很棒:
类 MyClass(对象):
@picklable_staticmethod
定义 foo():
打印“完成”。
我在这方面的尝试没有成功,特别是因为我无法从 foo
函数中提取所有者类。我什至愿意满足于显式规范(例如 @picklable_staticmethod(MyClass)
),但我不知道有什么方法可以在它所在的位置引用 MyClass
类正在定义中。
任何想法都会很棒!
与纳丹
最佳答案
这似乎可行。
class PickleableStaticMethod(object):
def __init__(self, fn, cls=None):
self.cls = cls
self.fn = fn
def __call__(self, *args, **kwargs):
return self.fn(*args, **kwargs)
def __get__(self, obj, cls):
return PickleableStaticMethod(self.fn, cls)
def __getstate__(self):
return (self.cls, self.fn.__name__)
def __setstate__(self, state):
self.cls, name = state
self.fn = getattr(self.cls, name).fn
诀窍是在从类中获取静态方法时阻止该类。
备选方案:您可以使用元类化为所有静态方法提供 .__parentclass__
属性。然后您可以子类化 Pickler
并为每个子类实例提供自己的 .dispatch
表,然后您可以修改该表而不影响全局调度表 (Pickler.dispatch
). pickle 、取消 pickle 和调用方法可能会更快一些。
关于python - 在 Python 中 pickle 静态方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1914261/