導語:本文章記錄了本人在學習Python基礎之數據結構篇的重點知識及我的心得,打算入門Python的朋友們能夠來一塊兒學習並交流。
本章重點:html
一、瞭解字符字節等概念,編解碼問題;
二、熟悉字符的規範化處理和雙模式API。
編解碼例子:python
s="São Paulo" a=s.encode('utf8') print(a)#b'S\xc3\xa3o Paulo' b=a.decode("utf8") print(b) output:São Paulo
一種重要的編碼, 是其餘編碼的基礎。
例如 cp1252 和Unicode( 注意, latin1 與 cp1252 的字節值是同樣的, 甚至連碼位也相同) 。Microsoft 制定的 latin1 超集
, 添加了有用的符號, 例如彎引號和€( 歐元) ; 有些 Windows 應用把它稱爲「ANSI」, 但它並非 ANSI 標準。目前 Web 中最多見的 8 位編碼; 與 ASCII 兼容
( 純 ASCII 文本是有效的 UTF-8 文本) 。瞭解有關Unicode錯誤的處理方法。正則表達式
編碼出現的錯誤在於編碼器可能沒法對字符串編碼,以中英文字符串爲例:編程
city="DaLian大連" print(city.encode("utf8"))#b'DaLian\xe5\xa4\xa7\xe8\xbf\x9e' print(city.encode("iso8859_1"))
輸出報錯:網絡
Traceback (most recent call last): File "D:\韓文承\編程工做空間\Fluent Python\section4-1.py", line 10, in <module> print(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大连'
想了解更多錯誤處理方式可查閱Python官方Library:
https://docs.python.org/3/lib...編輯器
解碼出現的錯誤在於陳舊的解碼器能解碼任何字節序列而不拋出錯誤,有時會解碼出無用的、亂碼的字符。以包含變音符號的字節序列爲例:函數
c=b"Montr\xe9al" 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 Python\section4-1.py", line 19, in <module> print(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。用�替代沒法解碼的字節
若是加載的模塊中包含utf_8以外的數據,那麼解釋器會報錯SyntaxError。
Chardet是Python的一個庫,能夠檢測出未知字節序列的編碼方式。
不要在二進制模式中打開文本文件。即便想判斷編碼,也該用Chardet!
字節序標記,這個標記針對非單字節非字符串外的其他數據(如short,int)指明字節存儲的方式,具體分爲大端存儲和小端存儲。
大端存儲第一個字節是高位,容易判斷數值的正負;
小端存儲第一個字節是地位,容易進行數值的運算。
須要注意:TCP/IP協議規定網絡字節序爲大端字節序。這意味着主機字節序若是是小端存儲必須轉化爲大端字節序才能經過網絡發送數據。
To Learn More:https://zhuanlan.zhihu.com/p/...
編碼默認值
在多系統處理文件時應顯式制定編碼,不然容易出現默認編碼器沒法解碼字節序列的狀況。
編輯器默認編碼查詢:locale.getpreferredencoding()#cp936
Unicode三明治原則
咱們能夠用一個簡單的原則處理編碼問題: 字節序列->字符串->字節序列
。就是說程序中應當僅處理字符串,當須要保存到文件系統或者傳輸的時候,編碼爲字節序列。
Unicode字符串規範化
碼位規範化函數:unicodedata.normalize(格式,字符串)
格式參數:
對大多數應用來講NFC是最好的規範化形式。
from unicodedata import normalize d="café" e="cafe\u0301" 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 服務與外界進行的交互的接口。通俗的理解是程序和程序之間的交互,交互就是傳遞數據,觸發功能。
正則表達式:能夠匹配文本片斷的模式。
通配符:
用反斜線對特殊符號進行轉義:
有時咱們只想用特殊符號如dot「."的字面意思,而非做爲通配符使用。例如匹配網站」baidu.com「中的點就須要轉義,變成"baidu\.com",即只匹配」baidu.com「字符集:
表示欲匹配字符的集合,相比較通配符中的點號而言範圍更小一些。例如[0-9A-F]能夠匹配一個十六進制的字符。
注意:一個字符集只能匹配一個字符,除非配合數量限定符使用!預約義字符集
選擇符和子模式:
此項欲匹配的範圍比字符集還要小。好比你只想匹配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參數介紹:
MatchObject是一次成功匹配後返回的對象類型,它支持以下的重要方法:
*和+這類數量限定符默認是貪婪的,即儘量多的匹配知足要求的字符串。只有在其後加上問號?方可變成非貪婪的。
貪婪與非貪婪eg:
import re greedy=re.compile(r"<.*>")#貪婪 non_greedy=re.compile(r"<.*?>")#非貪婪,利用問號限制 print(greedy.search("<H1>Chapter 1 - 介紹正則表達式</H1>")) print(non_greedy.search("<H1>Chapter 1 - 介紹正則表達式</H1>"))
輸出:
<_sre.SRE_Match object; span=(0, 28), match='<H1>Chapter 1 - 介紹正則表達式</H1>'> <_sre.SRE_Match object; span=(0, 4), match='<H1>'>
對字符串和字節序列進行re匹配:
import re text_str = "Ramanujan saw \u0be7\u0bed\u0be8\u0bef as 1729 = 1³ + 12³ = 9³ + 10³." 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', '1³', '12³', '9³', '10³'] 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...
用於返回指定的文件夾包含的文件或文件夾的名字的列表。這個列表以字母順序。
若是 filename 是 str 類型或bytes 類型,使用sys.getfilesystemencoding() 返回的編解碼器把 filename 編碼成字節序列; 不然, 返回未經修改的 filename 字節序列。
若是 filename 是 bytes 類型或 str 類型, 使用sys.getfilesystemencoding() 返回的編解碼器把 filename 解碼成字符串; 不然, 返回未經修改的 filename 字符串。