序列化

序列化

  • json模块
    可以在不同的系统见进行序列化/反序列化

    内置数据类型序列化和反序列化

    序列化 json.dumps()

    # 序列化
    # sort_keys参数: 表示序列化时是否对dict的key进行排序(dict默认是无序的)
    # indent参数: 表示缩进的意思
    # separators=(',',':')  去掉json字符串中:和,后的空白字符
    >>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)})
    '{"a": "str", "c": true, "b": 11.1, "e": 10, "d": null, "g": [4, 5, 6], "f": [1, 2, 3]}'
    

    反序列化 json.loads()

    >>> json.loads('{"a":"str","c":true,"b":11.1,"e":10,"d":null,"g":[4,5,6],"f":[1,2,3]}')
    {'c': True, 'e': 10, 'a': 'str', 'g': [4, 5, 6], 'd': None, 'f': [1, 2, 3], 'b': 11.1}
    

    dump()和load()函数示例:

    # 序列化到文件中
    >>> with open('test.json', 'w') as fp:
    ...     json.dump({'a':'str中国', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, fp, indent=4)
    
    # 反序列化文件中的内容
    >>> with open('test.json', 'r') as fp:
    ...     json.load(fp)
    {'e': 10, 'g': [4, 5, 6], 'b': 11.1, 'c': True, 'd': None, 'a': 'str中国', 'f': [1, 2, 3]}
    

    自定义数据类型的序列化/反序列化

    实现方式:

    • 转换函数实现
    • 继承JSONEncoder、JSONDecoder实现
    
    import json
    
    
    class Student:
    
    	def __init__(self, name, age):
        	self.name = name
        	self.age = age
    
    
    def student2dict(obj):
    	"""对象 --> dict"""
    	"""必须返回序列化结果"""
    	d = {}
    	d['__class__'] = obj.__class__.__name__  # 踩坑:obj.__class__ 造成返回不是序列化结果,抛错
    	d['__module__'] = obj.__module__
    	d.update(obj.__dict__)
    	return d
    
    
    class MyJSONEncoder(json.JSONEncoder):
    	def default(self, obj):
        	d = {}
        	d['__class__'] = obj.__class__.__name__  # 踩坑:obj.__class__ 造成返回不是序列化结果,抛错
        	d['__module__'] = obj.__module__
        	d.update(obj.__dict__)
        	return d
    
    
    def dict2student(dic):
    	"""dict --> 对象"""
    	"""传入的dict"""
    	if '__class__' in dic:
        	class_name = dic.pop('__class__')
        	module_name = dic.pop('__module__')
        	module = __import__(module_name)
        	class_ = getattr(module, class_name)
        	args = dict( (k, v) for k, v in dic.items())
        	ins = class_(**args)  # 解包成位置参数
    	else:
       		ins = dic
    	return ins
    
    
    class MyJSONDecoder(json.JSONDecoder):
    	def __init__(self):
        	super().__init__(object_hook=dict2student)
    	def dict2student(self, dic):
        	"""dict --> 对象"""
        	"""传入的dict"""
        	if '__class__' in dic:
            	class_name = dic.pop('__class__')
            	module_name = dic.pop('__module__')
            	module = __import__(module_name)
            	class_ = getattr(module, class_name)
            	args = dict((k, v) for k, v in dic.items())
            	ins = class_(**args)  # 解包成位置参数
        	else:
            	ins = dic
        	return ins
    
    stu = Student('Tom', 25)
    # default将对象转换为可序列为json对象,然后调用dumps()
    dump = json.dumps(stu,default=student2dict)  # {"__class__": "Student", "__module__": "__main__", "name": "Tom", "age": 25}
    dump1 = MyJSONEncoder().encode(stu)  # MyJSONEncoder.encode(stu) 这样调用会报错,因为encode(self, o)是一个实例方法,类外不能被类调用
    dump2 = MyJSONEncoder(separators=(',', ':')).encode(stu)
    dump3 = json.dumps(stu, cls=MyJSONEncoder)  # 类似于dump调用
    dump4 = json.dumps(stu, cls=MyJSONEncoder, separators=(',', ':'))
    
    # loads()方法先转换出一个dict对象,然后object_hook函数负责将dict转换为Student实例
    load = json.loads(dump,object_hook=dict2student)  # <__main__.Student object at 0x0000014F920EC278>
    load1 = MyJSONDecoder().decode(dump)
    load2 = json.loads(dump, cls=MyJSONDecoder)
    
    
  • pickle模块

    仅仅用于python内部数据序列化/反序列化.

    内置数据类型序列化/反序列化:

    import pickle
    
    var_a = {'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}
    
    # 序列化为字节
    var_b = pickle.dumps(var_a)
    var_c = pickle.loads(var_b)
    
    # 必须以二进制打开
    with open('pickle.txt','wb') as fp:
    	pickle.dump(var_a,fp)
    
    with open('pickle.txt','rb') as fp:
    	var_d = pickle.load(fp)
    

    自定义数据类型的序列化/反序列化:
    pickle不需要编写额外的处理函数或类,可以直接对自定义数据类型进行序列化/反序列化
    注意:dump和load需要以二进制打开文件

  • shelve模块

    内部封装的是pickle模块,只有一个open()函数,这个函数用于打开指定的文件(一个持久的字典),然后返回一个shelf对象.
    shelf类似于dict,可以进行在线操作对象.

    with shelve.open('student') as fp:
    	fp['name'] = 'Tom'
    	fp['age'] = 25
    
    with shelve.open('student') as fp:
    	for k,v in fp.items():
        	print(k,v)
    

比较

JSON是文本形式的存储,Pickle则是二进制形式(至少常用二进制)
JSON是人可读的,Pickle不可读(二进制形式及加密)
JSON广泛应用于除Python外的其他领域,Pickle是Python独有的。
JSON只能dump一些python的内置对象,Pickle可以存储几乎所有对象。

偏向应用特别是web应用方面,可以常用JSON格式. 偏向算法方面,尤其是机器学习,则应该使用cPickle.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值