Python基礎(十六)
- 2019 年 10 月 5 日
- 筆記
今日主要內容
- 內置模組(標準庫)
- 序列化
- hashlib
- collections
- 軟體開發規範
一、內置模組(標準庫)
(一)序列化模組
- 什麼是序列化?
- 將一種數據結構(如列表、字典)轉換為另一種特殊的數據結構(如字元串、bytes類型)的過程就是序列化過程
- 數據傳輸的過程中,傳輸的都是位元組,現在有一個列表需要傳輸,我需要將列錶轉換為字元串,在將字元串進行編碼,但對方最終接收到的是一個字元串,字元串是不能原封不動的還原成列表的,這時候就需要用到反序列化將字元串轉換回列表
1.json模組(重要)
json文件相當於編程界的普通話,是各種語言交互的樞紐,當數據需要在多種語言間傳輸,就必須將數據轉換成json字元串,對方將接受到的json字元串再轉換成對應語言的數據類型,完美還原
json模組方法介紹:
json.dumps() 將對象序列化 json.loads() 將對象反序列化 json.dump() 將對象序列化寫入文件 json.load() 將對象讀取後反序列化 dumps、loads:用於網路傳輸dump、load:用於文件寫讀
json.dumps()
- 函數定義:
dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) - 函數說明:將對象序列化為json格式的字元串,其餘參數中的
ensure_ascii:若對象中出現的非ascii字元(如中文)時會被轉換,若顯示原字元,指定ensure_ascii=False
import json print(json.dumps(["張旭東666"])) print(json.dumps(["張旭東666"], ensure_ascii=False)) 運行結果: ["u5f20u65edu4e1c666"] ["張旭東666"]- 函數定義:
json.loads()
- 函數定義:
loads(s, *, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) - 函數說明:將json格式的字元串反序列化
import json print(json.loads("[1,2,3,4]")) print(type(json.loads("[1,2,3,4]"))) 運行結果: [1, 2, 3, 4] <class 'list'>- 函數定義:
json.dump()
- 函數定義:
dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) - 函數說明:將對象轉換為json流寫入到文件(fp為文件句柄)中
import json with open("text.txt", "w", encoding="utf-8") as f: json.dump([1, 2, 3, 4], f)- 函數定義:
json.load()
- 函數定義:
load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) - 函數說明:讀取文件句柄並將字元串反序列化
with open("text.txt", encoding="utf-8") as f: lst = json.load(f) print(lst) print(type(lst)) 運行結果: [1, 2, 3, 4] <class 'list'>- 函數定義:
如果向文件中寫入多個json串,無法讀取,因為在文件中寫入的都是一行內容
- 解決方法1:將所有內容準備好了一次性寫入和讀取
import json lst = [{"k1": 1}, {"k2": 2}, {"k3": 3}] # 準備好放在一起 with open("text.txt", "w+", encoding="utf-8") as f: json.dump(lst, f) # 一起寫入 f.seek(0) for el in json.load(f): # 一起讀取 print(el) 運行結果: {'k1': 1} {'k2': 2} {'k3': 3}- 解決方法2:改用
dumps和loads對每一行分別進行處理
import json lst = [{"k1": 1}, {"k2": 2}, {"k3": 3}] with open("text.txt", "w+", encoding="utf-8") as f: for el in lst: f.write(json.dumps(el)+"n") # 利用write和dumps一行一行序列化寫入 f.seek(0) for line in f: print(json.loads(line)) # 一行一行讀取反序列化 運行結果: {'k1': 1} {'k2': 2} {'k3': 3}
2.pickle模組
pickle模組將所有數據類型和對象序列化轉換成bytes類型(不支援lambda匿名函數),還可以反序列化還原回原數據,pickle模組只能在python語言中使用,其他語言不識別
pickle模組支援多行序列化寫入和多行讀取反序列化功能
pickle模組方法介紹:
pickle.dumps() 將對象序列化 pickle.loads() 將對象反序列化 pickle.dump() 將對象序列化寫入文件 pickle.load() 將對象讀取後反序列化 dumps、loads:用於網路傳輸dump、load:用於文件寫讀- pickle的方法和json完全相同,與json的區別就是pickle序列化後是位元組,而json序列化後是字元串
3.shelve模組(了解)
- 了解一下就好,這裡不做介紹
(二)hashlib模組
hashlib模組被人稱為加密演算法、摘要演算法等,它的功能是用來對數據進行加密和文件校驗使用,通過模組中的功能函數將數據轉換為一個固定長度的字元串
數據轉換流程:
- 明文 —— 位元組 —— 密文
hashlib模組的特點:
- 轉換的密文沒有規律
- 操作不可逆
- 不同的bytes類型數據轉換的密文一定不同
import hashlib sha1 = hashlib.sha1() sha1.update("21".encode("utf-8")) # 將21轉換為密文 print(sha1.hexdigest()) sha1 = hashlib.sha1() sha1.update("12".encode("utf-8")) # 將12轉換為密文 print(sha1.hexdigest()) 運行結果: # 結果一定不同,且無規律 472b07b9fcf2c2451e8781e944bf5f77cd8457c8 7b52009b64fd0a2a49e6d8a939753077792b0554- 相同的bytes類型數據轉換的密文一定相同
import hashlib sha1 = hashlib.sha1() sha1.update("12".encode("gbk")) # 用gbk進行編碼 print(sha1.hexdigest()) sha1 = hashlib.sha1() sha1.update("12".encode("utf-8")) # 用utf-8進行編碼 print(sha1.hexdigest()) 運行結果: # 內容相同,無論編碼方式是什麼,密文一定相同, 7b52009b64fd0a2a49e6d8a939753077792b0554 7b52009b64fd0a2a49e6d8a939753077792b0554加密方式:
- md5
- sha1
- sha256
- sha512
模組應用一:對數據進行加密
方法介紹:
hashlib.md5() 對應加密方式初始化 obj.update() 向初始化的對象中添加要加密的內容,內容必須是位元組碼 obj.hexdigest() 對對象進行加密 普通加密:
import hashlib md5 = hashlib.md5() # 初始化使用md5加密方式的對象 md5.update("zxd666".encode("utf-8")) # 向對象添加要加密的內容,內容必須為位元組碼 print(md5.hexdigest()) # 進行加密 運行結果: fe02a10cda698ceb5a03022189199c49 # 相同明文,密文一定相同加鹽加密:
- 固定加鹽:
import hashlib md5 = hashlib.md5("鹽".encode("utf-8")) # 在初始化時可以對要加密的明文進行固定加鹽,鹽也需要轉換為位元組碼 md5.update("zxd666".encode("utf-8")) print(md5.hexdigest()) 運行結果: 2bc9ae4e838be80068a6e4963626b92c # 相同明文,密文一定相同- 動態加鹽:
import hashlib user = input("帳號:") pwd = input("密碼:") md5 = hashlib.md5(user.encode("utf-8")) # 利用帳號來給密碼加鹽,每個人的帳號都不同,起到了動態加鹽的效果 md5.update(pwd.encode("utf-8")) print(md5.hexdigest()) 運行結果: 帳號:zxd 密碼:zxd123 ddca7a4709d99ac8d1b3012b2e6a364aobj.update()方法可以多次添加需要加密的內容import hashlib md5 = hashlib.md5() md5.update("zxd".encode("utf-8")) md5.update("666".encode("utf-8")) # 可以分開多次添加 print(md5.hexdigest()) 運行結果: fe02a10cda698ceb5a03022189199c49 # 與上面例子中普通加密的密文相同
模組應用二:用於文件一致性校驗
- linux講究:一切皆文件,我們普通的文件,影片,音頻,圖片,以及應用程式等都是文件。我們都從網上下載過資源,比如我們下載的Python解釋器,當時你可能沒有注意過,其實你下載的時候都是帶一個MD5或者shax值的,為什麼? 我們的網路世界是很不安全的,經常會遇到病毒,木馬等,有些你是看不到的可能就植入了你的電腦中,那麼他們是怎麼來的? 都是通過網路傳入來的,就是你在網上下載一些資源的時候,趁虛而入,當然大部分被我們的瀏覽器或者殺毒軟體攔截了,但是還有一部分偷偷的進入你的磁碟中了。那麼我們自己如何驗證我們下載的資源是否有病毒呢?這就需要文件的一致性校驗了。在我們下載一個軟體時,往往都帶有一個MD5或者shax值,當我們下載完成這個應用程式時你要是對比大小根本看不出什麼問題,你應該對比他們的md5值,如果兩個md5值相同,就證明這個應用程式是安全的,如果你下載的這個文件的MD5值與服務端給你提供的不同,那麼就證明你這個應用程式肯定是植入病毒了(文件損壞的幾率很低),那麼你就應該趕緊刪除,不應該安裝此應用程式。
- 我們之前說過,md5計算的就是bytes類型的數據的轉換值,同一個bytes數據用同樣的加密方式轉化成的結果一定相同,如果不同的bytes數據(即使一個數據只是刪除了一個空格)那麼用同樣的加密方式轉化成的結果一定是不同的。所以,hashlib也是驗證文件一致性的重要工具。

文件校驗實例:
import hashlib def file_check(file_path): with open(file_path,mode='rb') as f1: sha256 = hashlib.md5() while 1: content = f1.read(1024) if content: sha256.update(content) else: return sha256.hexdigest() print(file_check('python-3.6.8-amd64.exe'))
(三)collections模組
- collections模組提供了一些額外的數據類型和一些集合類的操作
之前提到過的官方判斷可迭代對象和迭代器的方法:Iterable、Iterator
from collections import Iterable, Iterator lst = [1,2,3,4,5] l_iter = iter(lst) print(isinstance(lst, Iterable)) print(isinstance(l_iter, Iterator)) 運行結果: True TrueCounter類(統計)
- Counter類是一個計數器,可以用來統計每個元素出現的次數,返回的是一個Counter對象
from collections import Counter lst = [1, 2, 6, 2, 4, 4, 6, 2, 4, 5, 4, 4, 2, 3, 2, 1] print(dict(Counter(lst))) 運行結果: {1: 2, 2: 5, 6: 2, 4: 5, 5: 1, 3: 1}- Counter還可以用來去重
from collections import Counter lst = [1, 2, 6, 2, 4, 4, 6, 2, 4, 5, 4, 4, 2, 3, 2, 1] print(list(Counter(lst))) 運行結果: [1, 2, 6, 4, 5, 3]deque類(雙向隊列)
- deque類是一個雙向隊列,在雙向隊列之前先了解一下 棧 和 隊列 的定義
- 棧:FILO 先進後出(比如上下電梯轎廂)
- 隊列:FIFO 先進先出(所有的排隊)
- 利用deque類來建立雙向隊列,以及操作雙向隊列
from collections import deque q = deque() q.append(3) q.append(4) q.appendleft(2) q.appendleft(1) print(list(q)) print(q.pop()) print(q.popleft()) print(list(q)) 運行結果: [1, 2, 3, 4] 4 1 [2, 3]- deque類是一個雙向隊列,在雙向隊列之前先了解一下 棧 和 隊列 的定義
OrderedDict類(有序字典)
- 顧名思義,通過OrderedDict類創建的字典是有序的
from collections import OrderedDict dic = {"k1": 1, "k2": 2, "k3": 3} print(dic) od = OrderedDict({"k1": 1, "k2": 2, "k3": 3}) print(od) print(od["k1"]) 運行結果: {'k1': 1, 'k2': 2, 'k3': 3} OrderedDict([('k1', 1), ('k2', 2), ('k3', 3)]) # 位置固定 1 # 可以像正常字典取值defaultdict類(默認字典)
- 通過defaultdict類創建的字典可以給字典設置默認值,當key不存在時,直接獲取默認值
from collections import defaultdict df = defaultdicr(list) print(df["k1"]) 運行結果: []namedtuple類(命名元組)
- 通過namedtuple類創建元組可以給元組內的元素命名
from collections import namedtuple nt = namedtuple("num", ["x", "y"]) # 定義元組名、元素名(其實這裡是創建了一個類) p = nt(1, 2) print(p) print(p.x) print(p.y) 運行結果: num(x=1, y=2) 1 2
二、軟體開發規範
軟體開發規範:分文件管理,增強耦合性
bin 啟動文件目錄 lib 公共組件目錄 core 主邏輯目錄 db 相關數據目錄 log 日誌 conf 配置文件目錄