摘要:計算機中以字節為單位存儲和解釋信息,規定一個字節由八個二進制位構成,即個字節等于個比特。需要注意協議規定網絡字節序為大端字節序。以元組形式返回全部分組截獲的字符串。返回指定的組截獲的子串在中的結束索引子串最后一個字符的索引。
導語:本文章記錄了本人在學習Python基礎之數據結構篇的重點知識及個人心得,打算入門Python的朋友們可以來一起學習并交流。
本章重點:
1、了解字符字節等概念,編解碼問題;一、基本概念
2、熟悉字符的規范化處理和雙模式API。
Unicode
Unicode(統一碼、萬國碼、單一碼)是計算機科學領域里的一項業界標準,包括字符集、編碼方案等。Unicode 是為了解決傳統的字符編碼方案的局限而產生的,它為每種語言中的每個字符設定了統一并且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。
位
來自英文bit,音譯為“比特”,表示二進制位。位是計算機內部數據儲存的最小單位,11010100是一個8位二進制數。一個二進制位只可以表示0和1兩種狀態(21);兩個二進制位可以表示00、01、10、11四種(22)狀態;三位二進制數可表示八種狀態(23)。
字節
字節是計算機中數據處理的基本單位。計算機中以字節為單位存儲和解釋信息,規定一個字節由八個二進制位構成,即1個字節等于8個比特(1Byte=8bit)。八位二進制數最小為00000000,最大為11111111;通常1個字節可以存入一個ASCII碼,2個字節可以存放一個漢字國標碼。
字
計算機進行數據處理時,一次存取、加工和傳送的數據長度稱為字(word)。一個字通常由一個或多個(一般是字節的整數位)字節構成。例如286微機的字由2個字節組成,它的字長為16;486微機的字由4個字節組成,它的字長為32位機。
字長
字長是指cpu的每個字所包含的位數。根據計算機的不同,字長有固定的和可變的兩種。固定字長,即字長度不論什么情況都是固定不變的;可變字長,則在一定范圍內,其長度是可變的。計算的字長是指它一次可處理的二進創數字的數目。計算機處理數據的速率,自然和它一次能加工的位數以及進行運算的快慢有關。如果一臺計算機的字長是另一臺計算機的兩倍,即使兩臺計算機的速度相同,在相同的時間內,前者能做的工作是后者的兩倍。
碼位
又稱字符的標識。在Unicode標準中以4~6個十六進制數字表示,并加前綴“U+”。例如字母A的碼位是U+0041
編碼
把碼位轉換成字節序列,調用s.encode()
解碼
把字節序列轉換成碼位,調用s.decode()
編解碼例子:
s="S?o Paulo" a=s.encode("utf8") print(a)#b"Sxc3xa3o Paulo" b=a.decode("utf8") print(b) output:S?o Paulo二、編解碼問題 1、編解碼器
latin1( 即 iso8859_1)
一種重要的編碼, 是其他編碼的基礎。 例如 cp1252 和Unicode( 注意, latin1 與 cp1252 的字節值是一樣的, 甚至連碼位也相同) 。
cp1252
Microsoft 制定的 latin1 超集, 添加了有用的符號, 例如彎引號和€( 歐元) ; 有些 Windows 應用把它稱為“ANSI”, 但它并不是 ANSI 標準。
cp437
IBM PC 最初的字符集, 包含框圖符號。 與后來出現的 latin1 不兼容。
gb2312
用于編碼簡體中文的陳舊標準; 這是亞洲語言中使用較廣泛的多字節編碼之一。
utf-8
目前 Web 中最常見的 8 位編碼; 與 ASCII 兼容( 純 ASCII 文本是有效的 UTF-8 文本) 。
utf-16le
UTF-16 的 16 位編碼方案的一種形式; 所有 UTF-16 支持通過轉義序列( 稱為“代理對”, surrogate pair) 表示超過 U+FFFF 的碼位。
了解有關Unicode錯誤的處理方法。
2.1 UnicodeEncodeError編碼出現的錯誤在于編碼器可能無法對字符串編碼,以中英文字符串為例:
city="DaLian大連" print(city.encode("utf8"))#b"DaLianxe5xa4xa7xe8xbfx9e" print(city.encode("iso8859_1"))
輸出報錯:
Traceback (most recent call last): File "D:韓文承編程工作空間Fluent Pythonsection4-1.py", line 10, inprint(city.encode("iso8859_1")) UnicodeEncodeError: "latin-1" codec can"t encode characters in position 6-7: ordinal not in range(256)
原因在于這個latin1不會對中午編碼,所以我們需要處理這個EncodeError,處理如下:
print(city.encode("iso8859_1",errors="ignore"))#b"DaLian" print(city.encode("iso8859_1",errors="replace"))#b"DaLian??" print(city.encode("iso8859_1",errors="xmlcharrefreplace"))#b"DaLian大连"
errors="ignore"
跳過無法編碼的字符,這樣做通常不妥。
errors="replace"
用問號替代無法編碼的字符,雖然損壞了數據,但用戶收到了編碼有問題的信號。
errors="xmlcharrefreplace"
用xml實體代替無法編碼的字符。
想了解更多錯誤處理方式可查閱Python官方Library:
https://docs.python.org/3/lib...
解碼出現的錯誤在于陳舊的解碼器能解碼任何字節序列而不拋出錯誤,有時會解碼出無用的、亂碼的字符。以包含變音符號的字節序列為例:
c=b"Montrxe9al" print(c.decode("iso8859_1"))#Montréal print(c.decode("cp1252"))#Montréal print(c.decode("cp437"))#MontrΘal 輸出已經有問題了 print(c.decode("koi8_r"))#MontrИal KOI8_R是編碼俄文的,此處輸出了俄文字母 print(c.decode("utf8"))
報錯:
Traceback (most recent call last): File "D:韓文承編程工作空間Fluent Pythonsection4-1.py", line 19, inprint(c.decode("utf8")) UnicodeDecodeError: "utf-8" codec can"t decode byte 0xe9 in position 5: invalid continuation byte
原因在于utf_8檢測到c不是有效utf_8字符串,拋出UnicodeDecodeError。處理如下:
print(c.decode("utf8",errors="replace"))#Montr?al。用?替代無法解碼的字節2.3 SyntaxError
如果加載的模塊中包含utf_8之外的數據,那么解釋器會報錯SyntaxError。
3、ChardetChardet是Python的一個庫,可以檢測出未知字節序列的編碼方式。
不要在二進制模式中打開文本文件。即使想判斷編碼,也該用Chardet!
字節序標記,這個標記針對非單字節非字符串外的其余數據(如short,int)指明字節存儲的方式,具體分為大端存儲和小端存儲。
大端存儲第一個字節是高位,容易判斷數值的正負;
小端存儲第一個字節是地位,容易進行數值的運算。
需要注意:TCP/IP協議規定網絡字節序為大端字節序。這意味著主機字節序如果是小端存儲必須轉化為大端字節序才能通過網絡發送數據。
To Learn More:https://zhuanlan.zhihu.com/p/...
編碼默認值
在多系統處理文件時應顯式制定編碼,否則容易出現默認編碼器無法解碼字節序列的情況。
編輯器默認編碼查詢:locale.getpreferredencoding()#cp936
Unicode三明治原則
我們可以用一個簡單的原則處理編碼問題: 字節序列->字符串->字節序列。就是說程序中應當僅處理字符串,當需要保存到文件系統或者傳輸的時候,編碼為字節序列。
Unicode字符串規范化
碼位規范化函數:unicodedata.normalize(格式,字符串)
格式參數:
NFC:使用最少的碼位構造等價字符串
NFD :使用基字符和組合字符構造等價字符串
NFKC 和NFKD:將兼容字符分解
對大多數應用來說NFC是最好的規范化形式。
from unicodedata import normalize d="café" e="cafeu0301" print(normalize("NFC",d)==normalize("NFC",e))#True print(normalize("NFD",d)==normalize("NFD",e))#True
規范化之后兩個不同的碼位相等的。
保存文件之前最好用規范化函數unicodedata.normalize(“NFC”,字符串)清洗字符串
大小寫折疊函數:str.casefold()
自Python3.4起,str.lower()和str.casefold()不同的結果有116個碼位,占Unicode命名的總字符的0.11%
Unicode 排序:unicode collation algorithm, UCA 使用 PyUCA 庫。
下載地址:https://pypi.python.org/pypi/...
雙模式是指標準庫中一些函數能夠接受字符串或字節序列為參數,并根據類型進行處理。
API(Application Programming Interface)即應用程序接口。可以把 API 理解為一個軟件組件或是一個 Web 服務與外界進行的交互的接口。通俗的理解是程序和程序之間的交互,交互就是傳遞數據,觸發功能。
正則表達式:可以匹配文本片段的模式。
1.1語法介紹:通配符:
.點dot:能夠匹配任意的字符。
^尖號:從開始匹配,意味著開始的字符必須和partern一致方可匹配上,否則匹配返回none.。
$美元符號:從尾部開始匹配,尾部開始的字符必須和partern一致方可匹配上,否則匹配返回none.。
*星號:允許模式重復0次或多次。
+加號:允許模式重復1次或多次。
?問號:允許模式重復0次或1次。
{m,n}:允許模式重復m~n次。(貪婪匹配下直接匹配到n次)當m=n即為{m},只匹配m次。
用反斜線對特殊符號進行轉義:
有時我們只想用特殊符號如dot“."的字面意思,而非作為通配符使用。例如匹配網站”baidu.com“中的點就需要轉義,變成"baidu.com",即只匹配”baidu.com“
字符集:
表示欲匹配字符的集合,相比較通配符中的點號而言范圍更小一些。例如[0-9A-F]可以匹配一個十六進制的字符。
注意:一個字符集只能匹配一個字符,除非配合數量限定符使用!
預定義字符集
d,數字[0-9]
D,非數字[^d]
s,空白字符,包括空格,trnfv
S,非空白字符[^s]
w,單詞字符[A-Za-z0-9_]
W,非單詞字符[^w]
選擇符和子模式:
此項欲匹配的范圍比字符集還要小。比如你只想匹配python和people這兩個單詞,就可以用管道符號(|),即“python|people"。
如果操作的不是整個模式partern而是模式的一部分,圓括號括起來的部分稱作子模式,即“p(ython|eople)”
函數 | 描述 |
---|---|
re.compile(pattern, flags=0) | 根據正則表達式的字符串創建模式對象 |
re.search(pattern, string, flags=0) | 在字符串中尋找模式 |
re.match(pattern, string, flags=0) | 在字符串的開始處匹配模式 |
re.split(pattern, string, maxsplit=0, flags=0) | 根據模式的匹配項來分割字符串 |
re.findall(pattern, string, flags=0) | 列出字符串中模式的所有匹配項 |
re.finditer(pattern, string, flags=0) | 返回一個迭代器,其中包含滿足正則表達式要求的match objects |
re.sub(pattern, repl, string, count=0, flags=0) | 將字符串中所有pat的匹配項用repl替換 |
re.escape(pattern) 將字符串中所有特殊正則表達式字符轉義
Tips:re.compile構建模式,對于重復式的匹配效率更高。
flags參數介紹:
re.I 或re.IGNORECASE
使匹配忽略字母大小寫。
re.L或re.LOCALE
影響 “w, “W, “b, 和 “B,這取決于當前的本地化設置。
re.M或re.MULTILINE
使用本標志后,‘^’和‘$’匹配行首和行尾時,會增加換行符之前和之后的位置。
re.S或re.DOTALL
使點號這個特殊字符完全匹配任何字符,包括換行;沒有這個標志, “.” 匹配除了換行符外的任何字符。
re.X或re.VERBOSE
當該標志被指定時,在 RE 字符串中的空白符被忽略,除非該空白符在字符類中或在反斜杠之后。它也可以允許你將注釋寫入 RE,這些注釋會被引擎忽略;注釋用 “#”號 來標識,不過該符號不能在字符串或反斜杠之后。
MatchObject是一次成功匹配后返回的對象類型,它支持如下的重要方法:
group([group1, …]):
獲得一個或多個分組截獲的字符串;指定多個參數時將以元組形式返回。group1可以使用編號也可以使用別名;編號0代表整個匹配的子串;不填寫參數時,返回group(0);沒有截獲字符串的組返回None;截獲了多次的組返回最后一次截獲的子串。
groups():
以元組形式返回全部分組截獲的字符串。相當于調用group(1,2,…last)。
start([group]):
返回指定的組截獲的子串在string中的起始索引(子串第一個字符的索引)。group默認值為0。
end([group]):
返回指定的組截獲的子串在string中的結束索引(子串最后一個字符的索引+1)。group默認值為0。
span([group]):
返回(start(group), end(group))。
*和+這類數量限定符默認是貪婪的,即盡可能多的匹配滿足要求的字符串。只有在其后加上問號?方可變成非貪婪的。
貪婪與非貪婪eg:
import re greedy=re.compile(r"<.*>")#貪婪 non_greedy=re.compile(r"<.*?>")#非貪婪,利用問號限制 print(greedy.search("Chapter 1 - 介紹正則表達式
")) print(non_greedy.search("Chapter 1 - 介紹正則表達式
"))
輸出:
<_sre.SRE_Match object; span=(0, 28), match="Chapter 1 - 介紹正則表達式
"> <_sre.SRE_Match object; span=(0, 4), match="">
對字符串和字節序列進行re匹配:
import re text_str = "Ramanujan saw u0be7u0bedu0be8u0bef as 1729 = 13 + 123 = 93 + 103." text_byte=text_str.encode("utf_8") str_number=re.compile(r"d+") str_word=re.compile(r"w+") byte_number=re.compile(rb"d+") byte_word=re.compile(rb"w+") print("str_number",str_number.findall(text_str)) print("str_word",str_word.findall(text_str)) print("byte_number",byte_number.findall(text_byte)) print("byte_word",byte_word.findall(text_byte))
輸出:
str_number ["????", "1729", "1", "12", "9", "10"] byte_number [b"1729", b"1", b"12", b"9", b"10"] str_word ["Ramanujan", "saw", "????", "as", "1729", "13", "123", "93", "103"] byte_word [b"Ramanujan", b"saw", b"as", b"1729", b"1", b"12", b"9", b"10"]
分析:通過分別對字符串和字節序列進行數字、單詞字符的匹配操作,容易發現對字節序列的匹配僅限于ASCII中的數字和單詞字符,而對字符串的匹配會包含更多的泰米爾數字和上標等其他字符。
To Learn More: https://docs.python.org/3/lib...
os.listdir() :
用于返回指定的文件夾包含的文件或文件夾的名字的列表。這個列表以字母順序。
os.fsencode(filename):
如果 filename 是 str 類型或bytes 類型,使用sys.getfilesystemencoding() 返回的編解碼器把 filename 編碼成字節序列; 否則, 返回未經修改的 filename 字節序列。
os.fsdecode(filename):
如果 filename 是 bytes 類型或 str 類型, 使用sys.getfilesystemencoding() 返回的編解碼器把 filename 解碼成字符串; 否則, 返回未經修改的 filename 字符串。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/41473.html
摘要:字符編碼表,碼位碼元將編碼字符集中的碼位轉換成有限比特長度的整型值的序列。字符編碼方案,碼元序列化也稱為常說的序列化。每個字節里的二進制數就是字節序列。另一個情況則是壓縮字節序列的值,如或進程長度編碼等無損壓縮技術。 《流暢的Python》筆記。本篇主要講述不同編碼之間的轉換問題,比較繁雜,如果平時處理文本不多,或者語言比較單一,沒有多語言文本處理的需求,則可以略過此篇。 1. 前言 ...
摘要:上一篇文章標準庫內置類型文本序列類型下一篇文章二進制序列類型操作二進制數據的核心內置類型是和。另請參見內置類型。存在一個反向轉換函數,可以將對象轉換為對應的十六進制表示。返回子序列在范圍內非重疊出現的次數。 上一篇文章:Python標準庫---12、內置類型:文本序列類型(str)下一篇文章: 二進制序列類型 --- bytes, bytearray, memoryview 操作二進制...
摘要:處理文本的最佳實踐是三明治要盡早把輸入例如讀取文件時的字節序列解碼成字符串。這種三明治中的肉片是程序的業務邏輯,在這里只能處理字符串對象。 處理文本的最佳實踐是Unicode 三明治 要盡早把輸入(例如讀取文件時)的字節序列解碼成字符串。 這種三明治中的肉片是程序的業務邏輯,在這里只能處理字符串對象。 在其他處理過程中,一定不能編碼或解碼。 對輸出來說,則要盡量晚地把字符串編碼成字...
摘要:上一篇文章標準庫內置函數下一篇文章標準庫內置函數內置函數返回對象的長度元素個數。對表示單個字符的字符串,返回代表它碼點的整數。上一篇文章標準庫內置函數下一篇文章標準庫內置函數 上一篇文章:Python標準庫---3、內置函數(G-H-I-J-K)下一篇文章:Python標準庫---5、內置函數(P-K-R) 內置函數: showImg(https://segmentfault.com...
摘要:每個字符都可以編碼為唯一的序列。但在中還有其他的數字系統,通過其他方式是表示數字。事實上,是的完美子集。里的編碼與解碼的類型用于表示人類可讀的文本,可以包含任何字符。編碼的文本表示為二進制數據字節。 概述 在使用Python或者其他的編程語言,都會多多少少遇到編碼錯誤,處理起來非常痛苦。在Stack Overflow和其他的編程問答網站上,UnicodeDecodeError和Unic...
閱讀 1644·2021-10-25 09:46
閱讀 3239·2021-10-08 10:04
閱讀 2386·2021-09-06 15:00
閱讀 2786·2021-08-19 10:57
閱讀 2093·2019-08-30 11:03
閱讀 993·2019-08-30 11:00
閱讀 2393·2019-08-26 17:10
閱讀 3562·2019-08-26 13:36