學習廖雪峰Python3教程的pytho
- 2020 年 1 月 3 日
- 筆記
我們把變數從記憶體中變成可存儲或傳輸的過程稱之為序列化,在Python中叫pickling,在其他語言中也被稱之為serialization,marshalling,flattening等等,都是一個意思。
序列化之後,就可以把序列化後的內容寫入磁碟,或者通過網路傳輸到別的機器上。
序列化之後,就可以把序列化後的內容寫入磁碟,或者通過網路傳輸到別的機器上。
Python提供了pickle
模組來實現序列化。
import pickle
d = {"name":"Alice","age":22,"score":88}
pickle.dumps(d)
pickle.dumps()方法可以把任意的對象序列化成一個bytes,然後這個bytes就可以寫入文件,也可以用pickle.dump()方法直接把對象序列化後寫入一個文件對象
with open("dump.txt","wb") as f:
pickle.dump(d,f)
同樣我們把對象從磁碟讀到記憶體時,可以先把內容讀到一個bytes,然後用pickle.loads()方法反序列化出對象,也可以用pickle.load()方法從一個文件對象中直接反序列化出對象。
with open("dump.txt","rb")as f:
d = pickle.load(f)
print(d)
Pickle的問題和所有其他程式語言特有的序列化問題一樣,就是它只能用於Python,並且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的數據,不能成功地反序列化也沒關係。
=====================================正文=================================================
如果我們要在不同的程式語言之間傳遞對象,就必須把對象序列化為標準格式,比如XML,但更好的方法是序列化為JSON,因為JSON表示出來就是一個字元串,可以被所有語言讀取,也可以方便地存儲到磁碟或者通過網路傳輸。JSON不僅是標準格式,並且比XML更快,而且可以直接在Web頁面中讀取,非常方便。
Python內置的json模組提供了非常完善的Python對象到JSON格式的轉換。
import json
d = {"name":"Bob","age":22,"score":88}
json.dumps(d)
json.dumps()方法返回了str,就是標準的JSON。類似的,dump()方法可以直接把JSON寫入一個文件對象
with open("json.txt","w",encoding="utf-8") as f:
json.dump(d,f)
同樣要把JSON反序列化為Python對象,用loads或對應的load方法,前者把JSON的字元串反序列化,後者從文件對象中讀取字元串並反序列化
with open("json.txt","r")as f:
d = json.load(f)
print(d)
由於JSON標準規定JSON編碼是UTF-8,所以我們總是能正確地在Python的str與JSON的字元串之間轉換。
==========================JSON進階=============================
Python的dict對象可以直接序列化為JSON的{},不過很多時候,我們更喜歡用class表示對象,比如定義一個Student類,然後序列化
class Student(object):
def __init__(self,name,age,score):
self.name = name
self.age = age
self.score = score
s = Student("Bob",22,88)
print(json.dumps(s))
運行程式碼將會得到一個TypeError,原因是不是一個可序列化為JSON的對象
我們仔細看看dumps方法的參數列表,可以發現,除了第一個必須的obj參數外,dumps方法還提供了一大堆的可選參數,其中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))
下次遇到別的類的實例同樣也無法序列化為JSON,這個時候我們可以用class實例的__dict__屬性把任意的class實例變為dict:
print(json.dumps(s,default=lambda obj: obj.__dict__))
因為通常class實例都有一個都有一個__dict__屬性,它就是一個dict,用來儲存實例變數,也有少數例外,比如定義了__slots__的class。
如果我們要把JSON反序列化為一個Student對象實例,只要用json.loads()方法即可:
json_str = '{"age": 20, "score": 88, "name": "Bob"}'
print(json.loads(json_str))