zoukankan      html  css  js  c++  java
  • 20201214 Json与pickle数据序列化

    1-1
    文件处理时,只能存字符串或者二进制
    
    info = {
        'name':'alex',
        'age':22
    }
    f = open("test.text", "w")
    f.write(info)
    f.close()
    
    --->
    Traceback (most recent call last):
    TypeError: write() argument must be str, not dict
    1-1-1 
    那么就改成字符串
    
    info = {
        'name':'alex',
        'age':22
    }
    f = open("test.text", "w")
    f.write(str(info))
    f.close()
    
    成功存进去了
    把字典这种内存的数据类型,通过字符串存到硬盘上了,这个过程叫序列化
    序列化就是把内存的数据类型,变成字符串了
    
    有序列化就有反序列化,反序列化就是加载回来
    1-1-2
    在一个新的程序里,打开刚才的文件
    f = open("test.text","r")
    data = eval(f.read())
    f.close()
    print(data['age'])
    --->
    22
    这种方式,也可以用
    
    但是 eval 不是通用的东西,一种更标准更通用的方式是 Json
    1-2
    import json
    
    info = {
        'name':'alex',
        'age':22
    }
    f = open("test.text", "w")
    print(json.dumps(info))
    --->
    {"name": "alex", "age": 22}
    
    序列化的时候,不建议用 str,low
    打印结果也是变成字符串了
    1-2-1
    现在可以将结果写进去
    import json
    
    info = {
        'name':'alex',
        'age':22
    }
    f = open("test.text", "w")
    f.write(json.dumps(info))
    f.close()
    1-3
    反序列化时
    import json
    f = open("test.text","r")
    data = json.loads(f.read())
    
    print(data["age"])
    --->
    22
    序列化用 dumps 反序列化用 loads
    实现将内存数据对象存入硬盘,并读回来的功能
    2-1
    import json
    
    def sayhi(name):
        print("hello, ", name)
    
    # 现在将这个函数的内存地址当做一个 key
    
    info = {
        'name':'alex',
        'age':22,
        'func':sayhi    # 不要调用,调用就直接返回结果了,这是一个内存地址
    }
    
    f = open("test.text", "w")
    f.write(json.dumps(info))
    f.close()
    --->
    TypeError: Object of type function is not JSON serializable
    
    这不是可序列化的 json 类型,json 只能处理简单数据类型,字典,列表,字符串等
    json 是所有语言里面都通用的,所有语言都支持 json
    json 主要是用于不同语言之间的数据交互, 所以 json 只默认支持最简单的类型
    xml 和 json 的作用是一样的, xml 正在逐渐被 json 取代
    xml 是一种标记式语言
    2-1-1
    现在如果处理复杂的数据类型,应该怎么办?
    pickle 用法和 json 是完全一样的
    import pickle 
    def sayhi(name):
        print("hello, ", name)
    
    现在将这个函数的内存地址当做一个 key
    
    info = {
        'name':'alex',
        'age':22,
        'func':sayhi    不要调用,调用就直接返回结果了,这是一个内存地址
    }
    
    f = open("test.text", "w")
    f.write(pickle.dumps(info))
    f.close()
    
    打印的结果是二进制的,而且需要编码
    pickle 有自己的语法规则和映射的对应关系(这不是加密)
    2-1-2
    import pickle 
    def sayhi(name):
        print("hello, ", name)
    
    info = {
        'name':'alex',
        'age':22,
        'func':sayhi    
    }
    
    f = open("test.text", "wb")
    f.write(pickle.dumps(info))
    f.close()
    2-1-3 
    反序列化也是一样的
    用rb
    import pickle
    f = open("test.text","rb")
    
    data = pickle.loads(f.read())
    
    print(data)
    --->
    AttributeError: Can't get attribute 'sayhi' on <module '__main__' from 'c:\Us
    
    原因是 虽然 序列化时把内存地址序列化进去了
    sayhi 的内存地址,伴随程序执行结束后,就释放了,对象就找不到了
    反序列化时,是找不到这个地址的
    
    pickle 可以用于 python 的所有数据类型
    2-1-4
    import pickle
    
    def sayhi(name):
        print("hello,",name)
    
    f = open("test.text","rb")
    
    data = pickle.loads(f.read())
    
    print(data)
    --->
    {'name': 'alex', 'age': 22, 'func': <function sayhi at 0x0000000001E5C1E0>}
    2-1-5
    import pickle
    
    def sayhi(name):
        print("hello,",name)
    
    f = open("test.text","rb")
    
    data = pickle.loads(f.read())
    
    print(data["func"]("Alex"))
    --->
    hello, Alex
    None
    2-2
    如果序列化和反序列化的对象,只是名字一样
    反序列化时,多加了一个内容,或者替换了内容,能够对应吗?
    import pickle
    
    def sayhi(name):
        print("hello2,",name)
    
    f = open("test.text","rb")
    
    data = pickle.loads(f.read())
    
    print(data["func"]("Alex"))
    --->
    hello2, Alex
    None
    
    说明只要函数名一样,内容可以不一样
    因为,序列化时,序列化的不是内存地址,而是整个的内存对象
    两个程序中的内存地址不可能一样,因为两个程序是无法互相访问的
    函数也可以序列化,这就是 pickle
    2-3
    pickle 和 json 的区别,pickle 只能支持python本语言,只能在 python 中使用,
    java 是不认识 pickle 数据类型的,java 只认识 json
    3-1 
    除了 dump 和 load,其实还有一个方法
    可以把 dumps 更简化
    dump 的用法是,第一个是 obj 序列号内存对象, 第二个是 文件
    
    import pickle 
    def sayhi(name):
        print("hello, ", name)
    
    info = {
        'name':'alex',
        'age':22,
        'func':sayhi    
    }
    
    f = open("test.text", "wb")
    pickle.dump(info,f)   # f.write(pickle.dumps(info))
    # 两种方式是完全一样的,只是不用写 write 了,把文件句柄传进去
    
    f.close()
    3-2
    反序列化2
    有 dump 就有 load
    
    import pickle
    
    def sayhi(name):
        print("hello,",name)
    
    f = open("test.text","rb")
    
    # data = pickle.loads(f.read())
    data = pickle.load(f)
    
    print(data["func"]("Alex"))
    3-3
    可以 dump 两次 或者 三次吗?
    import json
    
    info = {
        'name':'alex',
        'age':22
    }
    f = open("test.text", "w")
    f.write(json.dumps(info))
    
    info['age'] = 21
    f.write(json.dumps(info))
    f.close()
    --->
    {"name": "alex", "age": 22}{"name": "alex", "age": 21}
    改完之后,存入两个字典
    3-4
    反序列化
    import json
    
    f = open("test.test","r")
    
    data = json.load(f)
    print(data)
    
    3.0 中 可以 dump 好多次,但是无法 load 好多次
    
    所以,写程序,只 dump 一次,load 一次;新写入的内容冲掉旧内容
    想存多个状态,就 dump 成多个文件
  • 相关阅读:
    es6 学习笔记
    正则表达式 学习笔记
    knockout 学习笔记
    错误笔记
    zepto 学习笔记
    Dialog提示框
    setContentView( )方法
    SVG图形之几何图形——学习笔记2
    SVG图形之SVG文件如何嵌入HTML文档——学习笔记1
    getchar()的用法
  • 原文地址:https://www.cnblogs.com/azxsdcv/p/14131893.html
Copyright © 2011-2022 走看看