是否可以 ujson.dumps() python class 实例(更快的深度复制)
is it possible to ujson.dumps() python class instance (faster deepcopy)
我正在尝试制作 class 实例的快速副本。 cPickle.loads(cPickle.dumps(),-1)
工作正常,几乎比 copy.deepcopy
快 5 倍,但我 read that ujson
is much faster than cPickle
。我无法让 ujson 使用自定义 class,是否可以这样做?
示例:
import cPickle as pickle
import ujson
class AClass(object):
def __init__(self):
print('init')
self.v = 10
self.z = [2,3,4]
self._zdict = dict(zip(self.z,self.z))
a = AClass()
a
#<__main__.AClass at 0x118b1d390>
# does not work with ujson
ua = ujson.dumps(a)
au = ujson.loads(ua)
au
#{u'v': 10, u'z': [2, 3, 4]}
# but works with pickle
pa = pickle.dumps(a)
ap = pickle.loads(pa)
ap
#<__main__.AClass at 0x117460190>
ujson
没有序列化 对象 ;它只是将其属性 dict
编码为 JSON 对象。那里没有足够的信息来完整地复制原始对象;最明显的迹象是 ujson.dumps
的输出中没有任何内容记录 class a
是什么的实例。
usjon
比 cPickle
快得多的原因是 cPickle
必须做更多的事情。
一个想法是定义您自己的协议,这是为 pickle 描述的概念的基础。
在 class:
中定义一个 __getstate__
和 __setsatte__
实例
class AClass(object):
def __init__(self, v, z):
self.v = v
self.z = z
self._zdict = dict(zip(self.z, self.z))
def __repr__(self):
return repr({'v': self.v, 'z': self.z, '_zdict': self._zdict})
def __getstate__(self):
return {'v': self.v, 'z': self.z}
def __setstate__(self, state):
self.__dict__.update(state)
self._zdict = dict(zip(self.z, self.z))
然后,您可以像这样定义一个 save()
和一个 load()
函数:
import importlib
import json
import io
def save(instance, dst_file):
data = {
'module': instance.__class__.__module__,
'class': instance.__class__.__name__,
'state': instance.__getstate__()}
json.dump(data, dst_file)
def load(src_file):
obj = json.load(src_file)
module_name = obj['module']
mod = importlib.import_module(module_name)
cls = getattr(mod, obj['class'])
instance = cls.__new__(cls)
instance.__setstate__(obj['state'])
return instance
简单用法(这里使用StringIO
代替classic文件):
a_class = AClass(10, [2, 3, 4])
my_file = io.StringIO()
save(a_class, my_file)
print(my_file.getvalue())
# -> {"module": "__main__", "class": "AClass", "state": {"v": 10, "z": [2, 3, 4]}}
my_file = io.StringIO(my_file.getvalue())
instance = load(my_file)
print(repr(instance))
# -> {'v': 10, 'z': [2, 3, 4], '_zdict': {2: 2, 3: 3, 4: 4}}
我正在尝试制作 class 实例的快速副本。 cPickle.loads(cPickle.dumps(),-1)
工作正常,几乎比 copy.deepcopy
快 5 倍,但我 read that ujson
is much faster than cPickle
。我无法让 ujson 使用自定义 class,是否可以这样做?
示例:
import cPickle as pickle
import ujson
class AClass(object):
def __init__(self):
print('init')
self.v = 10
self.z = [2,3,4]
self._zdict = dict(zip(self.z,self.z))
a = AClass()
a
#<__main__.AClass at 0x118b1d390>
# does not work with ujson
ua = ujson.dumps(a)
au = ujson.loads(ua)
au
#{u'v': 10, u'z': [2, 3, 4]}
# but works with pickle
pa = pickle.dumps(a)
ap = pickle.loads(pa)
ap
#<__main__.AClass at 0x117460190>
ujson
没有序列化 对象 ;它只是将其属性 dict
编码为 JSON 对象。那里没有足够的信息来完整地复制原始对象;最明显的迹象是 ujson.dumps
的输出中没有任何内容记录 class a
是什么的实例。
usjon
比 cPickle
快得多的原因是 cPickle
必须做更多的事情。
一个想法是定义您自己的协议,这是为 pickle 描述的概念的基础。 在 class:
中定义一个__getstate__
和 __setsatte__
实例
class AClass(object):
def __init__(self, v, z):
self.v = v
self.z = z
self._zdict = dict(zip(self.z, self.z))
def __repr__(self):
return repr({'v': self.v, 'z': self.z, '_zdict': self._zdict})
def __getstate__(self):
return {'v': self.v, 'z': self.z}
def __setstate__(self, state):
self.__dict__.update(state)
self._zdict = dict(zip(self.z, self.z))
然后,您可以像这样定义一个 save()
和一个 load()
函数:
import importlib
import json
import io
def save(instance, dst_file):
data = {
'module': instance.__class__.__module__,
'class': instance.__class__.__name__,
'state': instance.__getstate__()}
json.dump(data, dst_file)
def load(src_file):
obj = json.load(src_file)
module_name = obj['module']
mod = importlib.import_module(module_name)
cls = getattr(mod, obj['class'])
instance = cls.__new__(cls)
instance.__setstate__(obj['state'])
return instance
简单用法(这里使用StringIO
代替classic文件):
a_class = AClass(10, [2, 3, 4])
my_file = io.StringIO()
save(a_class, my_file)
print(my_file.getvalue())
# -> {"module": "__main__", "class": "AClass", "state": {"v": 10, "z": [2, 3, 4]}}
my_file = io.StringIO(my_file.getvalue())
instance = load(my_file)
print(repr(instance))
# -> {'v': 10, 'z': [2, 3, 4], '_zdict': {2: 2, 3: 3, 4: 4}}