全網最適合入門的物件導向程式設計教程:53 Python 字串與序列化-字串與字元編碼

FreakStudio發表於2024-09-28

全網最適合入門的物件導向程式設計教程:53 Python 字串與序列化-字串與字元編碼

image

摘要:

在 Python 中,字串是文字的表示,預設使用 Unicode 編碼,這允許你處理各種字符集,字元編碼是將字元轉換為位元組的規則,常見的編碼包括UTF-8、UTF-16和ASCII。

原文連結:

FreakStudio的部落格

往期推薦:

學嵌入式的你,還不會物件導向??!

全網最適合入門的物件導向程式設計教程:00 物件導向設計方法導論

全網最適合入門的物件導向程式設計教程:01 物件導向程式設計的基本概念

全網最適合入門的物件導向程式設計教程:02 類和物件的 Python 實現-使用 Python 建立類

全網最適合入門的物件導向程式設計教程:03 類和物件的 Python 實現-為自定義類新增屬性

全網最適合入門的物件導向程式設計教程:04 類和物件的Python實現-為自定義類新增方法

全網最適合入門的物件導向程式設計教程:05 類和物件的Python實現-PyCharm程式碼標籤

全網最適合入門的物件導向程式設計教程:06 類和物件的Python實現-自定義類的資料封裝

全網最適合入門的物件導向程式設計教程:07 類和物件的Python實現-型別註解

全網最適合入門的物件導向程式設計教程:08 類和物件的Python實現-@property裝飾器

全網最適合入門的物件導向程式設計教程:09 類和物件的Python實現-類之間的關係

全網最適合入門的物件導向程式設計教程:10 類和物件的Python實現-類的繼承和里氏替換原則

全網最適合入門的物件導向程式設計教程:11 類和物件的Python實現-子類呼叫父類方法

全網最適合入門的物件導向程式設計教程:12 類和物件的Python實現-Python使用logging模組輸出程式執行日誌

全網最適合入門的物件導向程式設計教程:13 類和物件的Python實現-視覺化閱讀程式碼神器Sourcetrail的安裝使用

全網最適合入門的物件導向程式設計教程:全網最適合入門的物件導向程式設計教程:14 類和物件的Python實現-類的靜態方法和類方法

全網最適合入門的物件導向程式設計教程:15 類和物件的 Python 實現-__slots__魔法方法

全網最適合入門的物件導向程式設計教程:16 類和物件的Python實現-多型、方法重寫與開閉原則

全網最適合入門的物件導向程式設計教程:17 類和物件的Python實現-鴨子型別與“file-like object“

全網最適合入門的物件導向程式設計教程:18 類和物件的Python實現-多重繼承與PyQtGraph串列埠資料繪製曲線圖

全網最適合入門的物件導向程式設計教程:19 類和物件的 Python 實現-使用 PyCharm 自動生成檔案註釋和函式註釋

全網最適合入門的物件導向程式設計教程:20 類和物件的Python實現-組合關係的實現與CSV檔案儲存

全網最適合入門的物件導向程式設計教程:21 類和物件的Python實現-多檔案的組織:模組module和包package

全網最適合入門的物件導向程式設計教程:22 類和物件的Python實現-異常和語法錯誤

全網最適合入門的物件導向程式設計教程:23 類和物件的Python實現-丟擲異常

全網最適合入門的物件導向程式設計教程:24 類和物件的Python實現-異常的捕獲與處理

全網最適合入門的物件導向程式設計教程:25 類和物件的Python實現-Python判斷輸入資料型別

全網最適合入門的物件導向程式設計教程:26 類和物件的Python實現-上下文管理器和with語句

全網最適合入門的物件導向程式設計教程:27 類和物件的Python實現-Python中異常層級與自定義異常類的實現

全網最適合入門的物件導向程式設計教程:28 類和物件的Python實現-Python程式設計原則、哲學和規範大彙總

全網最適合入門的物件導向程式設計教程:29 類和物件的Python實現-斷言與防禦性程式設計和help函式的使用

全網最適合入門的物件導向程式設計教程:30 Python的內建資料型別-object根類

全網最適合入門的物件導向程式設計教程:31 Python的內建資料型別-物件Object和型別Type

全網最適合入門的物件導向程式設計教程:32 Python的內建資料型別-類Class和例項Instance

全網最適合入門的物件導向程式設計教程:33 Python的內建資料型別-物件Object和型別Type的關係

全網最適合入門的物件導向程式設計教程:34 Python的內建資料型別-Python常用複合資料型別:元組和命名元組

全網最適合入門的物件導向程式設計教程:35 Python的內建資料型別-文件字串和__doc__屬性

全網最適合入門的物件導向程式設計教程:36 Python的內建資料型別-字典

全網最適合入門的物件導向程式設計教程:37 Python常用複合資料型別-列表和列表推導式

全網最適合入門的物件導向程式設計教程:38 Python常用複合資料型別-使用列表實現堆疊、佇列和雙端佇列

全網最適合入門的物件導向程式設計教程:39 Python常用複合資料型別-集合

全網最適合入門的物件導向程式設計教程:40 Python常用複合資料型別-列舉和enum模組的使用

全網最適合入門的物件導向程式設計教程:41 Python常用複合資料型別-佇列(FIFO、LIFO、優先順序佇列、雙端佇列和環形佇列)

全網最適合入門的物件導向程式設計教程:42 Python常用複合資料型別-collections容器資料型別

全網最適合入門的物件導向程式設計教程:43 Python常用複合資料型別-擴充套件內建資料型別

全網最適合入門的物件導向程式設計教程:44 Python內建函式與魔法方法-重寫內建型別的魔法方法

全網最適合入門的物件導向程式設計教程:45 Python實現常見資料結構-連結串列、樹、雜湊表、圖和堆

全網最適合入門的物件導向程式設計教程:46 Python函式方法與介面-函式與事件驅動框架

全網最適合入門的物件導向程式設計教程:47 Python函式方法與介面-回撥函式Callback

全網最適合入門的物件導向程式設計教程:48 Python函式方法與介面-位置引數、預設引數、可變引數和關鍵字引數

全網最適合入門的物件導向程式設計教程:49 Python函式方法與介面-函式與方法的區別和lamda匿名函式

全網最適合入門的物件導向程式設計教程:50 Python函式方法與介面-介面和抽象基類

全網最適合入門的物件導向程式設計教程:51 Python函式方法與介面-使用Zope實現介面

全網最適合入門的物件導向程式設計教程:52 Python函式方法與介面-Protocol協議與介面

更多精彩內容可看:

給你的 Python 加加速:一文速通 Python 平行計算

一文搞懂 CM3 微控制器除錯原理

肝了半個月,嵌入式技術棧大彙總出爐

電子計算機類比賽的“武林秘籍”

一個MicroPython的開源專案集錦:awesome-micropython,包含各個方面的Micropython工具庫

Avnet ZUBoard 1CG開發板—深度學習新選擇

SenseCraft 部署模型到Grove Vision AI V2影像處理模組

文件和程式碼獲取:

可訪問如下連結進行對文件下載:

https://github.com/leezisheng/Doc

image

本文件主要介紹如何使用 Python 進行物件導向程式設計,需要讀者對 Python 語法和微控制器開發具有基本瞭解。相比其他講解 Python 物件導向程式設計的部落格或書籍而言,本文件更加詳細、側重於嵌入式上位機應用,以上位機和下位機的常見串列埠資料收發、資料處理、動態圖繪製等為應用例項,同時使用 Sourcetrail 程式碼軟體對程式碼進行視覺化閱讀便於讀者理解。

相關示例程式碼獲取連結如下:https://github.com/leezisheng/Python-OOP-Demo

正文

字串與字元編碼

字串是 Python 中的基本型別,它所代表的是一組不可變的字元(即無法直接修改字串的某一索引對應的字元,需要轉換為列表處理),某種程度上可以認為字串是特殊的元組型別。

Python 中的字串都是透過 Unicode 表示的,Unicode 是一個字元編碼標準,那麼什麼是字元編碼標準呢?實際上,在電腦科學中,資料的處理與儲存均基於二進位制系統。對於文字資訊的處理,需先將其轉化為數字形式以適應計算機的運算邏輯。在計算機體系結構中,早期的設計以 8 位二進位制數,即一位元組,作為基本單位。數字形式以適應計算機的運算邏輯。在計算機體系結構中,早期的設計以 8 位二進位制數,即一位元組,作為基本單位。因此,一個位元組所能表示的最大整數值為 255,這是由二進位制數 11111111 轉化為十進位制數得出的結果。對於更大整數的表示,則需透過增加位元組數來實現。例如,兩個位元組可表示的最大整數值為 65535,而四個位元組則可表示的最大整數值高達 4294967295。

鑑於計算機技術的發源地是美國,早期的字元編碼主要基於 ASCII 標準,僅涵蓋 127 個字元,包括大小寫英文字母、數字和一些常用符號。然而,對於非英文字元,如中文,單個位元組的編碼方式顯然不足以滿足需求。為此,中國製定了 GB2312 編碼標準,採用至少兩個位元組的編碼方式來表示中文字元,並確保與 ASCII 編碼的相容性。在全球範圍內,不同的語言和文化背景導致了多樣化的編碼標準,如日本的 Shift_JIS 和韓國的 Euc-kr。這些不同的編碼標準在多語言混合的文字環境中可能導致顯示亂碼的問題。Unicode 又被稱為統一碼、萬國碼;它為每種語言中的每個字元設定了統一併且唯一的二進位制編碼,以滿足跨語言、跨平臺進行文字轉換、處理的要求。****從這個角度來講,我們可以把字串看作一個不可變的 Unicode 字元序列。

Unicode 標準詳細闡釋了字元如何以碼位(code point)的形式進行表達。碼位的取值範圍限定在 0 至 0x10FFFF 的整數範圍內,理論上涵蓋了大約 110 萬個可能的值,但實際分配的數字並未達到這一規模。在 Unicode 標準以及本文的論述中,碼位採用 U+265E 的表述方式,用以指代值為 0x265e 的字元,其十進位制表示為 9822。

此外,Unicode 標準彙編了眾多表格,這些表格詳盡地列出了眾多字元及其對應的碼位資訊。

image

上一段可以歸結為:一個 Unicode 字串是一系列碼位(從 0 到 0x10FFFF 或者說十進位制的 1,114,111 的數字)組成的序列。這一序列在記憶體中需被表示為一組碼元(code unit),碼元會對映成包含八個二進位制位的位元組。將 Unicode 字串翻譯成位元組序列的規則稱為字元編碼,或者編碼。

大家首先會想到的編碼可能是用 32 位的整數作為程式碼位,然後採用 CPU 對 32 位整數的表示法。字串“Python”用這種表示法可能會如下所示:

image

這種表示法非常直白,但也存在一些問題:

  • (1)不具可移植性;不同的處理器的位元組序不同;
  • (2)非常浪費空間:在大多數文字中,大部分碼位都小於 127 或 255,因此位元組 0x00 佔用了大量空間。相較於 ASCII 表示法所需的 6 個位元組,以上字串需要佔用 24 個位元組;
  • (3)與現有的 C 函式(如 strlen())不相容,因此需要採用一套新的寬字串函式。

因此這種編碼用得不多,人們轉而選擇其他更高效、更方便的編碼,比如 UTF-8。UTF-8 是最常用的編碼之一,Python 往往預設會採用它。UTF 代表“Unicode Transformation Format”,'8'表示編碼採用 8 位數。

UTF-8 編碼把一個 Unicode 字元根據不同的數字大小編碼成 1-6 個位元組,常用的英文字母被編碼成 1 個位元組,漢字通常是 3 個位元組,只有很生僻的字元才會被編碼成 4-6 個位元組。如果你要傳輸的文字包含大量英文字元,用 UTF-8 編碼就能節省空間。UTF-8 編碼還有一個額外的好處,就是 ASCII 編碼實際上可以被看成是 UTF-8 編碼的一部分,所以,大量只支援 ASCII 編碼的歷史遺留軟體可以在 UTF-8 編碼下繼續工作。

實際上,Unicode 可使用下列任何一種字元編碼方案來編碼:

  • (1)UTF-8 :UTF-8 是 Unicode 的一種可變長度編碼形式,它透明地保留了 ASCII 字元程式碼值。該形式在 Solaris Unicode 語言環境中用作檔案程式碼。
  • (2)UTF-16:UTF-16 是 Unicode 的一種 16 位編碼形式。在 UTF-16 中,多達 65,535 個字元被編碼為單個 16 位值。對映在 65,535 到 1,114,111 的字元被編碼為成對的 16 位值(代理)。
  • (3)UTF-32:UTF-32 是 Unicode 的一種固定長度的 21 位編碼形式,通常用在 32 位容器或資料型別中。該形式在 Solaris Unicode 語言環境中用作程序程式碼(寬字元程式碼)。

字串常見操作

從 Python 3.0 開始,str 型別包含了 Unicode 字元,這意味著用"unicode rocks!"、'unicode rocks!' 或三重引號字串語法建立的任何字串都會儲存為 Unicode。

需要注意的是,Python 不支援單字元型別,單字元在 Python 中也是作為一個字串使用。

str 類擁有大量的方法,使得字串的操作更加簡單。透過 Python 直譯器中的 dir 和 help 指令可以得知所有方法的用法。

print(help(str))

image

這裡對於字串的基本方法應用和運算不做贅述,僅在下文中總結一個文件。本章重點在於幫助大家瞭解字元編碼、序列化物件及應用正規表示式解析字串並匹配任意模式。下表中我們列出來 str 類的常見方法和作用。

方法 作用
lower\upper 返回 S 字串的小寫、大寫格式。對於以下背景為藍色、紅色的這些方法,需要注意輸入的字串是不會被改變的,而是返回一個全新的 str 例項。
title\capital 前者返回 S 字串中所有單詞首字母大寫且其他字母小寫的格式,後者返回首字母大寫、其他字母全部小寫的新字串。
swapcase swapcase()對 S 中的所有字串做大小寫轉換(大寫--> 小寫,小寫--> 大寫)。
istitle 注意它並不會嚴格執行英語語法定義中的標題格式,例如,Leigh Hunt 的詩 The Glove and the Lions 應該是一個合法的標題,儘管它並不是所有單詞的首字母都大寫了。Robert Service 的 The Gremation of Sam McGee 也是一個合法的標題,儘管最後一個單詞中間含有大寫字母。
isdecimal 檢查字串是否只包含十進位制字元。字串中若只包含十進位制字元返回 True,否則返回 False。該方法只存在於 unicode 物件中。注意:定義一個十進位制字串,只需要在字串前新增字首 'u' 即可。
isdigit 檢測字串是否只由數字組成,字串中至少有一個字元且所有字元都是數字則返回 True,否則返回 False。
Isnumeric 檢測字串是否只由數字組成。這種方法是隻適用於 unicode 物件。字串中只包含數字字元,則返回 True,否則返回 False。在使用 isdigit、isdecimal 和 isnumeric 方法時要注意許多 Unicode 字元也被認為是數字,而不僅僅是我們習慣使用的 10 個阿拉伯數字。更糟的是,我們用小數點組成的浮點數在字串中並不會被認為是小數,因此對於'45.2'來說,isdecimal()返回的是 False。真正的小數點字元 Unicode 中的值是 0660,因此 45.2 應該是 45\u06602。再者,這些方法不會驗證字串是否是合法的數字,對於"127.0.0.1"來說這 3 個方法都會返回 True。
isalnum 檢測字串是否由字母和數字組成。str 中至少有一個字元且所有字元都是字母或數字則返回 True,否則返回 False。
isalpha 檢測字串是否只由字母組成。字串中至少有一個字元且所有字元都是字母則返回 True,否則返回 False。
Center(width[, fillchar]) 將字串居中,左右兩邊使用 fillchar 進行填充,使得整個字串的長度為 width。fillchar 預設為空格。如果 width 小於字串的長度,則無法填充直接返回字串本身(不會建立新字串物件)。
ljust/rjust ljust()使用 fillchar 填充在字串 S 的右邊,使得整體長度為 width。rjust()則是填充在左邊。如果不指定 fillchar,則預設使用空格填充。如果 width 小於或等於字串 S 的長度,則無法填充,直接返回字串 S(不會建立新字串物件)。
zfill 用 0 填充在字串 S 的左邊使其長度為 width。如果 S 前右正負號 +/- ,則 0 填充在這兩個符號的後面,且符號也算入長度。如果 width 小於或等於 S 的長度,則無法填充,直接返回 S 本身(不會建立新字串物件)。
Count(sub[, start[, end]]) 返回字串 S 中子串 sub 出現的次數,可以指定從哪裡開始計算(start)以及計算到哪裡結束(end),索引從 0 開始計算,不包括 end 邊界。
endswith/startswith endswith() 檢查字串 S 是否已 suffix 結尾,返回布林值的 True 和 False。suffix 可以是一個元組(tuple)。可以指定起始 start 和結尾 end 的搜尋邊界。同理 startswith()用來判斷字串 S 是否是以 prefix 開頭。
find\rfind\index\rindex find()搜尋字串 S 中是否包含子串 sub,如果包含,則返回 sub 的索引位置,否則返回"-1"。可以指定起始 start 和結束 end 的搜尋位置。index()和 find()一樣,唯一不同點在於當找不到子串時,丟擲 ValueError 錯誤。rfind()則是返回搜尋到的最右邊子串的位置,如果只搜尋到一個或沒有搜尋到子串,則和 find()是等價的。
Translate\maketrans str.maketrans()生成一個字元一一對映的 table,然後使用 translate(table)對字串 S 中的每個字元進行對映。可以用該方法實現字串的簡單加密。注意,maketrans(x[, y[, z]]) 中的 x 和 y 都是字串,且長度必須相等。
partition(sep)/rpartition(sep) 搜尋字串 S 中的子串 sep,並從 sep 處對 S 進行分割,最後返回一個包含 3 元素的元組:sep 左邊的部分是元組的第一個元素,sep 自身是元組的二個元素,sep 右邊是元組的第三個元素。partition(sep) 從左邊第一個 sep 進行分割, rpartition(sep) 從右邊第一個 sep 進行分割。如果搜尋不到 sep,則返回的 3 元素元組中,有兩個元素為空。partition()是後兩個元素為空,rpartition()是前兩個元素為空。以下幾個字串方法返回或作用於字串。
Split(sep=None,maxsplit=-1)Rsplit(sep=None,maxsplit=-1)Splitlines([keepends]) 都是用來分割字串,並生成一個列表。split()根據 sep 對 S 進行分割,maxsplit 用於指定分割次數,如果不指定 maxsplit 或者給定值為"-1",則會從做向右搜尋並且每遇到 sep 一次就分割直到搜尋完字串。如果不指定 sep 或者指定為 None,則改變分割演算法:以空格為分隔符,且將連續的空白壓縮為一個空格。rsplit()和 split() 是一樣的,只不過是從右邊向左邊搜尋。splitlines()用來專門用來分割換行符。可以指定各種換行符,常見的是\n、\r、\r\n 。如果指定 keepends 為 True,則保留所有的換行符。
join(iterable) 將可迭代物件(iterable)中的字串使用 S 連線起來。注意,iterable 中必須全部是字串型別,否則報錯。它接受一個字串列表作為引數,並返回列表中所有字串透過原始字串連線起來之後的字串。
strip\lstrip\rstrip 分別是移除左右兩邊、左邊、右邊的字元 char。如果不指定 chars 或者指定為 None,則預設移除空白(空格、製表符、換行符)。唯一需要注意的是,chars 可以是多個字元序列。在移除時,只要是這個序列中的字元,都會被移除。
replace(old, new, count) 把 str 中的 old 替換成 new,如果 count 指定,則替換不超過 count 次.。
expandtabs(N) 將字串 S 中的\t 替換為一定數量的空格。預設 N=8。注意, expandtabs(8)不是將\t 直接替換為 8 個空格。例如 'xyz\tab'.expandtabs() 會將\t 替換為 5 個空格,因為"xyz"佔用了 3 個字元位。另外,它不會替換換行符( \n 或 \r )時。

關於這些方法具體使用,可以看以下連結:

https://pythonhowto.readthedocs.io/zh-cn/latest/string.html#

同時,這裡我們回顧一下字串的跳脫字元和運算子,參考菜鳥教程即可:

image

image

相關文章