1. 程式人生 > >python 學習二十五天(python內置模塊之序列化模塊)

python 學習二十五天(python內置模塊之序列化模塊)

nan close 分行 name 寫入 打開文件 rip ide 傳遞

今日主要內容

1.python內置模塊-序列化模塊

python中的序列化模塊

json 所有的編程語言都通用的序列化格式....它支持的數據類型非常有限 數字 字符串 列表 字典

pickle 只能在python語言的程序之間傳遞數據用的..pickle支持python中所有的數據類型

shelve python3.* 之後才有的

2.摘要模塊---hashlib

3.一道經典面試題

第一.python內置模塊---序列化

***所有的導入模塊都需要把import放在文件首位

什麽叫序列化

能存儲在文件中的一定是字符串 或者是 字節
能在網絡上傳輸的 只有字節

所以為了能夠對我們需要的數據進行存儲或者傳輸就需要對數據進行序列化

以前是怎樣序列化的呢?

dic = {"大表哥":(190,90)}
dic --> 字符串 # 序列化
字符串 --> dic # 反序列化

由此可知:

序列化 等於創造一個序列,就是創造一個字符串

實例化 等於創建一個實例

如何使用json

#講解標準序列化的操作

1.json

import json

例:dumps和loads

#序列化

import json
dic = {小樣:(190,90,捏腳)}
ret = json.dumps(dic)
ret1 = json.dumps(dic,ensure_ascii=False)
print(ret)
print
(ret1)

#反序列化

import json
dic = {小樣:(190,90,捏腳)}
ret = json.dumps(dic)
ret1 = json.dumps(dic,ensure_ascii=False)
res = json.loads(ret)
res1 = json.loads(ret1) 
print(type(res),res) #返回傳入數據格式

例:dump和load 是直接將對象序列化之後寫入文件,依賴一個文件句柄

dic = {小樣:(190,90,捏腳)}
#序列化
f = open(小樣,w,encoding=utf-8)
json.dump(dic,f) 
f.close()
結果:(文件內容)
{
"\u5c0f\u6837": [190, 90, "\u634f\u811a"]}

增加一個標準輸出的參數:

import json
dic = {小樣:(190,90,捏腳)}
f = open(小樣,w,encoding=utf-8)
json.dump(dic,f,ensure_ascii=False)
f.close()
結果:
{"小樣": [190, 90, "捏腳"]}

反序列化輸出

import json
dic = {小樣:(190,90,捏腳)}
f = open(小樣,encoding=utf-8)
wt = json.load(f)
f.close()
print(wt)

結果: (原型輸出)
{小樣: [190, 90, 捏腳]}

如何應付多個字典序列化?

例:

import json
dic1 = {"大表哥":(190,90,捏腳)}
dic2 = {"2表哥":(190,90,捏腳)}
dic3 = {"3表哥":(190,90,捏腳)}
f = open(大表哥,a,encoding=utf-8)
str1 = json.dumps(dic1)  #分別進行序列化,並序列化後進行手動換行
f.write(str1+\n)
str2 = json.dumps(dic2)
f.write(str2+\n)
str3 = json.dumps(dic3)
f.write(str3+\n)
f.close()

結果: 大表哥文件內容
{"\u5927\u8868\u54e5": [190, 90, "\u634f\u811a"]}
{"2\u8868\u54e5": [190, 90, "\u634f\u811a"]}
{"3\u8868\u54e5": [190, 90, "\u634f\u811a"]}

多字典的反序列化

f = open(大表哥,r,encoding=utf-8)
for line in f:
    print(json.loads(line.strip()))
f.close()

#結果   #利用循環對文件進行分別讀取,然後json.loads進行反序列化

{大表哥: [190, 90, 捏腳]}
{2表哥: [190, 90, 捏腳]}
{3表哥: [190, 90, 捏腳]}

dumps序列化 loads反序列化 只在內存中操作數據 主要用於網絡傳輸 和多個數據與文件打交道
dump序列化 load反序列化 主要用於一個數據直接存在文件裏—— 直接和文件打交道

其他參數

Serialize obj to a JSON formatted str.(字符串表示的json對象) 
Skipkeys:默認值是False,如果dict的keys內的數據不是python的基本類型(str,unicode,int,long,float,bool,None),設置為False時,就會報TypeError的錯誤。此時設置成True,則會跳過這類key 
ensure_ascii:,當它為True的時候,所有非ASCII碼字符顯示為\uXXXX序列,只需在dump時將ensure_ascii設置為False即可,此時存入json的中文即可正常顯示。) 
If check_circular is false, then the circular reference check for container types will be skipped and a circular reference will result in an OverflowError (or worse). 
If allow_nan is false, then it will be a ValueError to serialize out of range float values (nan, inf, -inf) in strict compliance of the JSON specification, instead of using the JavaScript equivalents (NaN, Infinity, -Infinity). 
indent:應該是一個非負的整型,如果是0就是頂格分行顯示,如果為空就是一行最緊湊顯示,否則會換行且按照indent的數值顯示前面的空白分行顯示,這樣打印出來的json數據也叫pretty-printed json 
separators:分隔符,實際上是(item_separator, dict_separator)的一個元組,默認的就是(‘,’,’:’);這表示dictionary內keys之間用“,”隔開,而KEY和value之間用“:”隔開。 
default(obj) is a function that should return a serializable version of obj or raise TypeError. The default simply raises TypeError. 
sort_keys:將數據根據keys的值進行排序。 
To use a custom JSONEncoder subclass (e.g. one that overrides the .default() method to serialize additional types), specify it with the cls kwarg; otherwise JSONEncoder is used.

json 在寫入多次dump的時候 不能對應執行多次load來取出數據,pickle可以
json 如果要寫入多個元素 可以先將元素dumps序列化,f.write(序列化+‘\n‘)寫入文件
    讀出元素的時候,應該先按行讀文件,在使用loads將讀出來的字符串轉換成對應的數據類型

2.pickle #序列化輸出

用法:import pickle

用法也有: dumps和loads 基於內 存中

     dump和load #寫在文件中

實例化:

import pickle
dic = {(190,90,捏腳):"大表哥"}
f = open(大表哥2,wb)  # 使用pickle dump必須以+b的形式打開文件
pickle.dump(dic,f)
f.close()

結果:
#創建了一個叫‘大表哥2‘的文件,並傳入byte形式的文件

反序列化

import pickle
f = open(大表哥2,rb)
print(pickle.load(f))
f.close()

結果:
{(190, 90, 捏腳): 大表哥}

pickle寫入多行實例:

import pickle

# 關於寫多行
dic1 = {"大表哥":(190,90,捏腳)}
dic2 = {"2表哥":(190,90,捏腳)}
dic3 = {"3表哥":(190,90,捏腳)}
f = open(大表哥3,wb)
pickle.dump(dic1,f)
pickle.dump(dic2,f)
pickle.dump(dic3,f)
f.close()

#讀取多行
f = open(大表哥3,rb)  #打開文件
while True:
    try:
        print(pickle.load(f))
    except EOFError:   #讀取時報錯,需要把錯誤忽略
        break

序列化自定義類的對象

例題:

class A:
    def __init__(self,name,age):
        self.name=name
        self.age=age
a = A(alex,80)
import json
# json.dumps(a)  #報錯json不能序列化類對象
import pickle
ret = pickle.dumps(a)
print(ret)
obj = pickle.loads(ret)
print(obj.__dict__)

報錯信息如下:
Traceback (most recent call last):
  File "F:/Python-script-2/s11-day25/練習.py", line 50, in <module>
    json.dumps(a)
  File "C:\Python36\lib\json\__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "C:\Python36\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Python36\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "C:\Python36\lib\json\encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type A is not JSON serializable

註銷後結果如下:

b‘\x80\x03c__main__\nA\nq\x00)\x81q\x01}q\x02(X\x04\x00\x00\x00nameq\x03X\x04\x00\x00\x00alexq\x04X\x03\x00\x00\x00ageq\x05KPub.‘
{‘name‘: ‘alex‘, ‘age‘: 80}

模塊hashlib —— 摘要算法

#也是一些算法的集合,有好多算法
# 字符串 --> 數字
# 不同的字符串 --> 數字一定不同
# 無論在哪臺機器上,在什麽時候計算,對相同的字符串結果總是一樣的
# 摘要過程不可逆

# 用法
文件的一致性校驗
密文驗證的時候加密

常用加密算法

md5算法 通用的算法
# sha算法 安全系數更高,sha算法有很多種,後面的數字越大安全系數越高,
# 得到的數字結果越長,計算的時間越長

例:將密碼用16進制的加密

import hashlib
m = hashlib.md5()
m.update(alex3714.encode(utf-8))
print(m.hexdigest())

現在由於有人講常用的md5加密過的簡單密碼進行存儲,然後去破解這種,俗稱撞庫

為了解決這個問題,所以我們想到了一個解決辦法,叫做加鹽

m = hashlib.md5(wahaha.encode(utf-8))  #在對hashlib進行實例化的時候,先添加規定的字符串
m.update(123456.encode(utf-8))
print(m.hexdigest()) 

還有更安全的動態加鹽,就是將用戶名動態添加.

username = alex
m = hashlib.md5(username[:2:2].encode(utf-8)) #動態截取用戶名步長2,0-2的字符串
m.update(123456.encode(utf-8))
print(m.hexdigest()) 

經典面試題,

通過這道題能夠搞清楚set()集合去重的原理

題意:

# 寫一個類 定義100個對象
# 擁有三個屬性 name age sex
# 如果兩個對象的name 和 sex完全相同
# 我們就認為這是一個對象
# 忽略age屬性
# 做這100個對象的去重工作

class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def  __hash__(self):
        return hash(self.name + self.sex)
        # hash算法本身就存在了 且直接在python中就能調用
        # 姓名相同 性別相同的對象的hash值應該相等才行
        # 姓名性別都是字符串
      def __eq__(self.other):
            if self.name == other.name and self.sex ==other.sex
                return Trun


obj_lst = []
obj_lst.append(Person(alex,80,male))
obj_lst.append(Person(alex,70,male))
obj_lst.append(Person(alex,60,male))
obj_lst.append(Person(boss_jin,50,male))
obj_lst.append(Person(boss_jin,40,male))
obj_lst.append(Person(boss_jin,30,male))
obj_lst.append(Person(nezha,20,male))
obj_lst.append(Person(nezha,10,male))
obj_lst = set(obj_lst)
for obj in obj_lst:print(obj.name)

結論:set對一個對象序列的去重 依賴於這個對象的兩個方法 hash eq

python 學習二十五天(python內置模塊之序列化模塊)