1. 程式人生 > >編碼轉換,基礎,copy

編碼轉換,基礎,copy

閱讀目錄

一,編碼轉換

  1. ASCII : 最早的編碼. ⾥⾯有英⽂⼤寫字⺟, ⼩寫字⺟, 數字, ⼀些特殊字元.

   沒有中⽂, 8個01程式碼, 8個bit, 1個byte

  2. GBK: 中⽂國標碼, ⾥⾯包含了ASCII編碼和中⽂常⽤編碼. 16個bit, 2個byte

  3. UNICODE: 萬國碼, ⾥⾯包含了全世界所有國家⽂字的編碼. 32個bit, 4個byte, 包含了 ASCII

  4. UTF-8: 可變⻓度的萬國碼. 是unicode的⼀種實現. 最⼩字元佔8位

    1.英⽂: 8bit 1byte

    2.歐洲⽂字:16bit 2byte

    3.中⽂:24bit 3byte

  綜上, 除了ASCII碼以外, 其他資訊不能直接轉換.

  在python3的記憶體中. 在程式運⾏階段. 使⽤的是unicode編碼.

    因為unicode是萬國碼. 什麼內容都可以進⾏顯⽰. 那麼在資料傳輸和儲存的時候由於unicode比較浪費空間和資源.

  需要把 unicode轉存成UTF-8或者GBK進⾏儲存. 怎麼轉換呢.

  在python中可以把⽂字資訊進⾏編碼. 編碼之後的內容就可以進⾏傳輸了.

  編碼之後的資料是bytes型別的資料.其實啊. 還是原來的 資料只是經過編碼之後表現形式發⽣了改變⽽已.

bytes的表現形式:

  1. 英⽂ b'alex' 英⽂的表現形式和字串沒什麼兩樣

  2. 中⽂ b'\xe4\xb8\xad' 這是⼀個漢字的UTF-8的bytes表現形式

s = "alex"
print(s.encode("utf-8")) # 將字串編碼成UTF-8
print(s.encode("GBK")) # 將字串編碼成GBK
結果:
b'alex'
b'alex'
s = ""
print(s.encode("UTF-8")) # 中⽂編碼成UTF-8
print(s.encode("GBK")) # 中⽂編碼成GBK
結果:
b'\xe4\xb8\xad
' b'\xd6\xd0'

記住: 英⽂編碼之後的結果和源字串⼀致. 中⽂編碼之後的結果根據編碼的不同. 編碼結果也不同.

    我們能看到. ⼀箇中⽂的UTF-8編碼是3個位元組. ⼀個GBK的中⽂編碼是2個位元組.

    編碼之後的型別就是bytes型別. 在⽹絡傳輸和儲存的時候我們python是儲存和儲存的bytes 型別.

    那麼在對⽅接收的時候. 也是接收的bytes型別的資料. 我們可以使⽤decode()來進⾏解 碼操作.

   把bytes型別的資料還原回我們熟悉的字串:

s = "我叫李嘉誠"
print(s.encode("utf-8")) #
b'\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a'
print(b'\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a'.decod
e("utf-8")) # 解碼

編碼和解碼的時候都需要制定編碼格式. 

s = "我是⽂字" bs = s.encode("GBK")
# 我們這樣可以獲取到GBK的⽂字
# 把GBK轉換成UTF-8
# ⾸先要把GBK轉換成unicode. 也就是需要解碼
s = bs.decode("GBK") # 解碼
# 然後需要進⾏重新編碼成UTF-8
bss = s.encode("UTF-8") # 重新編碼
print(bss)

基礎的補充

我們補充給幾個資料型別的操作

lst = [1,2,3,4,5,6]
 
for i in lst:
    lst.append(7) # 這樣寫法就會一直持續新增7
    print(lst)
print(lst)

列表: 迴圈刪除列表中的每⼀個元素

li = [11, 22, 33, 44]
for e in li:
 li.remove(e)
print(li)
結果:
[22, 44]

分析原因: for的運⾏過程. 會有⼀個指標來記錄當前迴圈的元素是哪⼀個, ⼀開始這個指標指向第0 個.

然後獲取到第0個元素. 緊接著刪除第0個. 這個時候. 原來是第⼀個的元素會⾃動的變成 第0個.

然後指標向後移動⼀次, 指向1元素. 這時原來的1已經變成了0, 也就不會被刪除了.

 

⽤pop刪除試試看:

li = [11, 22, 33, 44]
for i in range(0, len(li)):
 del li[i]
print(li)
結果: 報錯
# i= 0, 1, 2 刪除的時候li[0] 被刪除之後. 後⾯⼀個就變成了第0個.
# 以此類推. 當i = 2的時候. list中只有⼀個元素. 但是這個時候刪除的是第2個 肯定報錯啊

經過分析發現. 迴圈刪除都不⾏. 不論是⽤del還是⽤remove. 都不能實現. 那麼pop呢?

for el in li:
 li.pop() # pop也不⾏
print(li)
結果:
[11, 22]

只有這樣才是可以的:

for i in range(0, len(li)): # 迴圈len(li)次, 然後從後往前刪除
 li.pop()
print(li)

或者.用另一種類表來記錄你要刪除的內容.然後迴圈的刪除

li = [11, 22, 33, 44]
del_li = []
for e in li:
 del_li.append(e)
for e in del_li:
 li.remove(e)
 
print(li)

注意:

  由於刪除元素會導致元素的索引改變,所以容易出現問題,儘量不要在迴圈中直接去刪除元素,可以吧要刪除的元素新增到另一個集合中然後在批量刪除

dict中的fromkey(),可以幫助我們通過list來建立一個dict

dic = dict.fromkeys(["jay", "JJ"], ["周杰倫", "麻花藤"])
print(dic)
結果:
{'jay': ['周杰倫', '麻花藤'], 'JJ': ['周杰倫', '麻花藤']}

程式碼中的元素在迭代過程中是不允許進行刪除的

dic = {'k1': 'alex', 'k2': 'wusir', 's1': '⾦⽼板'}
# 刪除key中帶有'k'的元素
for k in dic:
  if 'k' in k:
 del dic[k] # dictionary changed size during iteration, 在迴圈迭
代的時候不允許進⾏刪除操作
print(dic)

那怎麼辦呢? 把要刪除的元素暫時先儲存在⼀個list中, 然後迴圈list, 再刪除

dic = {'k1': 'alex', 'k2': 'wusir', 's1': '⾦⽼板'}
dic_del_list = []
# 刪除key中帶有'k'的元素
for k in dic:
 if 'k' in k:
 dic_del_list.append(k)
for el in dic_del_list:
 del dic[el]
print(dic)

型別轉換:

  元組 => 列表 list(tuple)

  列表 => 元組 tuple(list)

  list=>str str.join(list)

  str=>list str.split()

  轉換成False的資料:

   0,'',None,[],(),{},set() ==> False 

深淺拷貝

lst1 = ["⾦⽑獅王", "紫衫⻰王", "⽩眉鷹王", "⻘翼蝠王"]
lst2 = lst1
print(lst1)
print(lst2)
lst1.append("楊逍")
print(lst1)
print(lst2)
結果:
['⾦⽑獅王', '紫衫⻰王', '⽩眉鷹王', '⻘翼蝠王', '楊逍']
['⾦⽑獅王', '紫衫⻰王', '⽩眉鷹王', '⻘翼蝠王', '楊逍']
 
 
dic1 = {"id": 123, "name": "謝遜"}
dic2 = dic1
print(dic1)
print(dic2)
dic1['name'] = "範瑤"
print(dic1)
print(dic2)
結果:
{'id': 123, 'name': '謝遜'}
{'id': 123, 'name': '謝遜'}
{'id': 123, 'name': '範瑤'}
{'id': 123, 'name': '範瑤'}

對於list, set, dict來說, 直接賦值. 其實是把記憶體地址交給變數. 並不是複製⼀份內容. 所以. lst1的記憶體指向和lst2是⼀樣的. lst1改變了, lst2也發⽣了改變

淺拷貝

lst1 = ["何炅", "杜海濤","周渝⺠"]
lst2 = lst1.copy()
lst1.append("李嘉誠")
print(lst1)
print(lst2)
print(id(lst1), id(lst2))
結果:
兩個lst完全不⼀樣. 記憶體地址和內容也不⼀樣. 發現實現了記憶體的拷⻉
lst1 = ["何炅", "杜海濤","周渝⺠", ["麻花藤", "⻢芸", "周筆暢"]]
lst2 = lst1.copy()
lst1[3].append("⽆敵是多磨寂寞")
print(lst1)
print(lst2)
print(id(lst1[3]), id(lst2[3]))
結果:
['何炅', '杜海濤', '周渝⺠', ['麻花藤', '⻢芸', '周筆暢', '⽆敵是多磨寂寞']]
['何炅', '杜海濤', '周渝⺠', ['麻花藤', '⻢芸', '周筆暢', '⽆敵是多磨寂寞']]
4417248328 4417248328

淺拷⻉. 只會拷⻉第⼀層. 第⼆層的內容不會拷⻉. 所以被稱為淺拷⻉

深拷⻉

import copy
lst1 = ["何炅", "杜海濤","周渝⺠", ["麻花藤", "⻢芸", "周筆暢"]]
lst2 = copy.deepcopy(lst1)
lst1[3].append("⽆敵是多磨寂寞")
print(lst1)
print(lst2)
print(id(lst1[3]), id(lst2[3]))
結果:
['何炅', '杜海濤', '周渝⺠', ['麻花藤', '⻢芸', '周筆暢', '⽆敵是多磨寂寞']]
['何炅', '杜海濤', '周渝⺠', ['麻花藤', '⻢芸', '周筆暢']]
4447221448 4447233800

都不⼀樣了.

深度拷貝. 把元素內部的元素完全進行拷貝複製. 不會產⽣⼀個改變另⼀個跟著 改變的問題 補充⼀個知識點:

最後我們來看⼀個⾯試題:

a = [1, 2]
a[1] = a
print(a[1])