python3(三十八) serialize


"""  """
__author__on__ = 'shaozhiqi  2019/9/24'

# !/usr/bin/env python3
# -*- coding: utf-8 -*-

# 在程序運行的過程中,所有的變量都是在內存中,比如,定義一個dict:
d = dict(name='Bob', age=20, score=88)
# 我們把變量從內存中變成可存儲或傳輸的過程稱之為**序列化**,在Python中叫pickling
# 序列化之后,就可以把序列化后的內容寫入磁盤,或者通過網絡傳輸到別的機器上。
# 反過來,把變量內容從序列化的對象重新讀到內存里稱之為反序列化,即unpickling。
# Python提供了pickle模塊來實現序列化。
import pickle

d = dict(name='Bob', age=20, score=88)
pickle.dumps(d)
# pickle.dumps()方法把任意對象序列化成一個bytes,然后,就可以把這個bytes寫入文件。
# 或者用另一個方法pickle.dump()直接把對象序列化后寫入一個file-like Object:
f = open('dump.txt', 'wb')
pickle.dump(d, f)
f.close()
# 看看寫入的dump.txt文件,一堆亂七八糟的內容,這些都是Python保存的對象內部信息。如下:
# �}q (X   nameqX   BobqX   ageqKX   scoreqKXu.

# -----------------------------------pickle反序列化------------------------------------
# 當我們要把對象從磁盤讀到內存時,可以先把內容讀到一個bytes,
# 然后用pickle.loads()方法反序列化出對象,也可以直接用pickle.load()方法從一個file-like Object中直接反序列化出對象。
# 我們打開另一個Python命令行來反序列化剛才保存的對象:
f = open('dump.txt', 'rb')
d = pickle.load(f)
f.close()
print(d)  # {'name': 'Bob', 'age': 20, 'score': 88}
# 當然,這個變量和原來的變量是完全不相干的對象,它們只是內容相同而已。
#
# Pickle的問題和所有其他編程語言特有的序列化問題一樣,就是它只能用於Python,並且可能不同版本的Python彼此都不兼容,
# 因此,只能用Pickle保存那些不重要的數據,不能成功地反序列化也沒關系。

# ------------------------------------------json----------------------------------
# 如果我們要在不同的編程語言之間傳遞對象,就必須把對象序列化為標准格式,
# 比如XML,但更好的方法是序列化為JSON,因為JSON表示出來就是一個字符串,
# 可以被所有語言讀取,也可以方便地存儲到磁盤或者通過網絡傳輸。
# JSON不僅是標准格式,並且比XML更快,而且可以直接在Web頁面中讀取,非常方便。

# JSON類型        Python類型
# {}            dict
# []            list
# "string"        str
# 1234.56        int或float
# true/false    True/False
# null            None

# -----------------Python對象->JSON--------------------------------------------
import json

d = dict(name='Bob', age=20, score=88)
json_d = json.dumps(d)
print(json_d)  # {"name": "Bob", "age": 20, "score": 88}
# dumps()方法返回一個str,內容就是標准的JSON。類似的,dump()方法可以直接把JSON寫入一個file-like Object。

# 要把JSON反序列化為Python對象,用loads()或者對應的load()方法,前者把JSON的字符串反序列化,
# 后者從file-like Object中讀取字符串並反序列化:
json_str = '{"age": 20, "score": 88, "name": "Bob"}'
dictvlaue = json.loads(json_str)
print(dictvlaue)
print(type(dictvlaue))  # <class 'dict'>
# 可以看到轉化為了dict類型

# ----------------------------------------------------------------------------------
# Python的dict對象可以直接序列化為JSON的{},
# 不過,很多時候,我們更喜歡用class表示對象,比如定義Student類,然后序列化:

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)


# print(json.dumps(s))
# TypeError: Object of type Student is not JSON serializable

# 錯誤的原因是Student對象不是一個可序列化為JSON的對象。
# 可選參數default就是把任意一個對象變成一個可序列為JSON的對象,我們只需要為Student專門寫一個轉換函數,再把函數傳進去即可:

def student2dict(std):
    return {
        'name': std.name,
        'age': std.age,
        'score': std.score
    }


# 這樣,Student實例首先被student2dict()
# 函數轉換成dict,然后再被順利序列化為JSON:
print(json.dumps(s, default=student2dict))  # {"name": "Bob", "age": 20, "score": 88}

# 那么問題來了,難道我們每轉化一個類為json都需要為其寫一個轉化函數嗎?
# 因為通常class的實例都有一個__dict__屬性,它就是一個dict,用來存儲實例變量。
# 也有少數例外,比如定義了__slots__的class。
print('student:', json.dumps(s, default=lambda obj: obj.__dict__))


# student: {"name": "Bob", "age": 20, "score": 88}

# 同樣的道理,如果我們要把JSON反序列化為一個Student對象實例,
# loads()方法首先轉換出一個dict對象,然后,我們傳入的object_hook函數負責把dict轉換為Student實例:
def dict2student(d):
    return Student(d['name'], d['age'], d['score'])


json_str = '{"age": 20, "score": 88, "name": "Bob"}'
student2 = json.loads(json_str, object_hook=dict2student)
print('json-student:', student2.name)  # json-student: Bob

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM