我一直试图挑选一个包含对静态类方法的引用的对象。
Pickle失败(例如在module.MyClass.foo
上)说明它无法被腌制,因为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
进程进行更改(例如,使用copy_reg
),但以下模式会很棒:
class MyClass(object):
@picklable_staticmethod
def foo():
打印“完成。”
我对此的尝试都没有成功,特别是因为我无法从foo
函数中提取所有者类。我甚至愿意接受明确的规范(例如@picklable_staticmethod(MyClass)
),但我不知道有什么方法可以引用MyClass
类来定义它。
任何想法都会很棒!
Yonatan
答案 0 :(得分:5)
这似乎有效。
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
)的情况下修改它。然后,腌制,去除斑点和调用方法可能会快一些。
答案 1 :(得分:0)
我认为python在不让pickle成为static方法对象方面是正确的 - 因为不可能挑选实例或类方法!这样的对象在其背景之外没有多大意义:
import pickle
def dosomething(a, b):
print a, b
class MyClass(object):
dosomething = staticmethod(dosomething)
o = MyClass()
pickled = pickle.dumps(dosomething)
这是可行的,这就是应该做的事情 - 定义一个函数,腌制它,并在某个类中使用静态方法这样的函数。
如果您有需要的用例,请写下来,我很乐意与您讨论。