除了一个外序列化所有属性
怎么写一个 __getstate__
方法,能把一个对象的几乎所有属性都保存起来,但又能排除掉一些呢?
我有一个对象,它有很多属性,其中有一个是指向实例方法的。实例方法是不能被保存的,所以当我尝试保存这个对象时就会出错:
class Foo(object):
def __init__(self):
self.a = 'spam'
self.b = 'eggs'
self.c = 42
self.fn = self.my_func
def my_func(self):
print 'My hovercraft is full of eels'
import pickle
pickle.dumps(Foo()) # throws a "can't pickle instancemethod objects" TypeError
这个 __getstate__
方法解决了这个问题,但我得手动列出所有我想保存的属性:
def __getstate__(self):
return { 'a': self.a, 'b': self.b, 'c': self.c }
如果我的对象有很多属性,或者这些属性经常变化,这样做就不太方便,也不容易维护。
我能想到的唯一替代办法就是写一个辅助函数,遍历对象的属性,根据属性的类型决定是否把它们添加到字典里。
6 个回答
4
你可以直接把那些不好的东西删掉:
def __getstate__(self):
state = self.__dict__
del state[...]
return state
6
使用之前回答中的 is_instance_method
方法:
def __getstate__(self):
return dict((k, v) for k, v in self.__dict__.iteritems()
if not is_instance_method(getattr(self, k)))
虽然我们也可以通过一种不那么“神奇”的方式来执行 is_instance_method
操作,比如拿一个已知的实例方法,比如 my_func
,然后查看它的类型。
def __getstate__(self):
instancemethod = type(self.my_func)
return dict((k, v) for k, v in self.__dict__.iteritems()
if not isinstance(getattr(self, k), instancemethod))
14
我能想到的唯一替代方案就是写一个辅助函数,这个函数会遍历一个对象的属性,然后根据属性的类型决定是否把它们加到字典里。
是的,我觉得如果你想要一些“魔法”来让自己变得懒惰(或者允许动态添加属性),那这基本上就是你能做的了。要记住,“pickle
处理不了这个”并不是你可能不想把某些东西放进序列化状态的唯一原因。
不过,这并没有你想象的那么难,前提是你已经有了判断“我应该序列化这个吗?”的逻辑代码:
def __getstate__(self):
return {k:v for (k, v) in self.__dict__.items() if should_pickle(v)}