• Python序列化-pickle和json模块


    Python的“file-like object“就是一种鸭子类型。对真正的文件对象,它有一个read()方法,返回其内容。但是,许多对象,只要有read()方法,都被视为“file-like object“。许多函数接收的参数就是“file-like object“,你不一定要传入真正的文件对象,完全可以传入任何实现了read()方法的对象。

    程序运行时,所有的变量都保存在内存中,程序结束后,内存回收,没有保存的变量还是原样的。

    所以想要持久化变量,就需要从内存中读取,保存到磁盘上,这个过程称作序列化-pickling

    反之,从磁盘读取为对象,称为反序列化-unpickling

    pickle

    Python提供的pickle模块很简单的将对象序列化为二进制类型,再进行二进制到文件的写入;

    或者直接点的,直接将对象序列化后写入file-like-object

    1.对象序列化为二进制,pickle.dumps()方法直接操作对象

    import pickle
    
    mylist = [1,3,5,'ac']
    
    ban = pickle.dumps(mylist)
    >>>ban
    b'x80x03]qx00(Kx01Kx03Kx05Xx02x00x00x00acqx01e.' #这里得到一个二进制数据类型

    1.1.pickle反序列化,pickle.loads(),主义这里loads()方法读取的是二进制数据

    >>>pickle.loads(mylist)
    [1,3,5,'ac']

    2.对象直接序列化为文件对象和反序列化;object--->>>file-like-object

    序列化,pickle.dump()方法

    import pickle
    
    mylist = [1,2,3,'abc']
    f = open('mylist.txt','wb')#以二进制写入
    pickle.dump(mylist,f)
    f.close()#文件操作完成后关闭,否则造成无法读写报错EOFError: Ran out of input

    反序列化,pickle.load()方法

    
    

    JSON

    如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。

    JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:

    JSON类型                            Python类型

    {}                dict

    []                 list

    "str"                                 str

    123                  int或float

    ture/false              Ture/False

    null                None

    使用json需要导入json模块,JSON标准规定JSON编码是UTF-8,所以我们总是能正确地在Python的str与JSON的字符串之间转换。

    序列化和反序列化完全和pickle一致

    序列化为file-like-object,json.dump()方法

    import json
    
    mylist = [1,2,3,'abc']
    f = open('mylist.txt','wb')#以二进制写入
    json.dunmp(mylist,f)
    f.close()#文件操作完成后关闭,否则造成无法读写报错EOFError: Ran out of input

    file-like-object反序列化,json.load()方法

    f = open('mylist.txt','rb') #二进制打开
    >>>json.load(f)
    [1,2,3,'abc']
    >>>f.close()

    类对象的序列化

    import json
    
    class Student(object):
        def __init__(self,name,age):
                self.name = name 
                self.age = age
    
    s = Student('tom',20)
    >>>json.dump(s)
    TypeError: <__main__.Student object at 0x10603cc50> is not JSON serializable
    
    报错类型错误,json不可将实例Student序列化

    dumps()可以提供很多参数

    json.dumps(objfp*skipkeys=Falseensure_ascii=Truecheck_circular=Trueallow_nan=Truecls=Noneindent=Noneseparators=Nonedefault=Nonesort_keys=False**kw)

    default参数可以增加一个函数,将Student对象转化为一个dict,dict是可以序列化的

    def todict(stu):
        return{
            'name':stu.name,
            'age':stu.age
    }

    default参数为函数

    import json
    
    class Student(object):
        def __init__(self,name,age):
                self.name = name 
                self.age = age
    
    s = Student('tom',20)
    >>>json.dump(s,default=todict)
    {'name','tom','age':20}

    或者快捷方式,

    import json
    
    class Student(object):
        def __init__(self, name, age, score):
            self.name = name
            self.age = age
            self.score = score
    
    s = Student('tom', 20, 88)
    
    print(json.dumps(s,default=lambda obj:obj.__dict__))
    {'name':'tom','age':20,'score':88}

    因为通常class的实例都有一个__dict__属性,它就是一个dict,用来存储实例变量。也有少数例外,比如定义了__slots__的class。

    __slots__ = (),这个方法用来限制实例的属性,作用域仅限当前的类,当父类中有__slots__属性时,子类中并没有限制,当子类中定义__slots__时,子类的实例限制就是子类本身加上父类的__slots__。

    反序列化

    json.loads(s*encoding=Nonecls=Noneobject_hook=Noneparse_float=Noneparse_int=Noneparse_constant=Noneobject_pairs_hook=None**kw)

    json.loads()方法也object_hook提供函数参数,用来反序列化

    import json
    
    class Student(object):
        def __init__(self, name, age, score):
            self.name = name
            self.age = age
            self.score = score
    
    
    s = Student('Bob', 20, 88)
    
    jsonstr = json.dumps(s,default=lambda obj:obj.__dict__)
    
    print(jsonstr)
    
    def dicttoobj(d):
        return Student(d['name'],d['age'],d['score'])
    
    print(json.loads(jsonstr,object_hook=dicttoobj))
    {"name": "Bob", "age": 20, "score": 88}
    <__main__.Student object at 0x000002518657C8D0>

    得到Student对象

    Python语言特定的序列化模块是pickle,但如果要把序列化搞得更通用、更符合Web标准,就可以使用json模块。

  • 相关阅读:
    C#多线程下更新UI的几种方法
    .net WebApi使用swagger 美化接口文档
    C#内存管理
    LINQ 推迟查询的执行
    C#多播委托详解
    泛型委托
    使用 ref 和 out 传递数组注意事项
    何时使用委托而不使用接口
    委托中的协变和逆变
    细说SQL Server数据类型
  • 原文地址:https://www.cnblogs.com/mzc1997/p/7651491.html
Copyright © 2020-2023  润新知