摘要:每個字符都可以編碼為唯一的序列。但在中還有其他的數字系統,通過其他方式是表示數字。事實上,是的完美子集。里的編碼與解碼的類型用于表示人類可讀的文本,可以包含任何字符。編碼的文本表示為二進制數據字節。
概述
在使用Python或者其他的編程語言,都會多多少少遇到編碼錯誤,處理起來非常痛苦。在Stack Overflow和其他的編程問答網站上,UnicodeDecodeError和UnicodeEncodeError也經常被提及。本篇教程希望能幫你認識Python編碼,并能夠從容的處理編碼問題。
本教程提到的編碼知識并不限定在Python,其他語言也大同小異,但我們依然會以Python為主,來演示和講解編碼知識。
通過該教程,你將學習到如下的知識:
獲取有關字符編碼和數字系統的概念
理解編碼如何使用Python的str和bytes
通過int函數了解Python對數字系統的支持
熟悉Python字符編碼和數字系統相關的內置函數
什么是字符編碼現在的編碼規則已經有好多了,最簡單、最基本是的ASCII編碼,只要是你學過計算機相關的課程,你就應該多少了解一點ASCII編碼,他是最小也是最適合了解字符編碼原理的編碼規則。具體如下:
小寫英文字符:a-z
大寫英文字符:A-Z
符號: 比如 $和!
空白符:回車、換行、空格等
一些不可打印的字符: 比如b等
那么,字符編碼的定義到底是什么了?它是一種將字符(如字母,標點符號,符號,空格和控制字符)轉換為整數并最終轉換為bit進行存儲的方法。 每個字符都可以編碼為唯一的bit序列。 如果你對bit的概念不了解,請不要擔心,我們后面會介紹。
ASCII碼的字符被分為如下幾組:
ASCII表一共包括128個字符,如果你想了解整個ASCII表,這里有
Python string模塊string模塊是python里處理字符串很方便的模塊,它包括了整個ASCII字符,讓我們來看看部分string模塊源碼:
# From lib/python3.7/string.py whitespace = " vf" ascii_lowercase = "abcdefghijklmnopqrstuvwxyz" ascii_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ascii_letters = ascii_lowercase + ascii_uppercase digits = "0123456789" hexdigits = digits + "abcdef" + "ABCDEF" octdigits = "01234567" punctuation = r"""!"#$%&"()*+,-./:;<=>?@[]^_`{|}~""" printable = digits + ascii_letters + punctuation + whitespace
你可以在Python中這樣使用string模塊:
>>> import string >>> s = "What"s wrong with ASCII?!?!?" >>> s.rstrip(string.punctuation) "What"s wrong with ASCII"什么是bit
學過計算機相關課程的同學,應該都知道,bit是計算機內部存儲單位,只有0和1兩個狀態(二進制),我們上面所說的ASCII表,都是一個10進制的數字表示一個字符,而這個10進制數字,最終會轉換成0和1,存儲在計算機內部。例如(第一列是10進制數字,第二列是二進制,第三列是計算機內部存儲結果):
這是一種在Python中將ASCII字符串表示為位序列的方便方法。 ASCII字符串中的每個字符都被偽編碼為8位,8位序列之間有空格,每個字符代表一個字符:
>>> def make_bitseq(s: str) -> str: ... if not s.isascii(): ... raise ValueError("ASCII only allowed") ... return " ".join(f"{ord(i):08b}" for i in s) >>> make_bitseq("bits") "01100010 01101001 01110100 01110011" >>> make_bitseq("CAPS") "01000011 01000001 01010000 01010011" >>> make_bitseq("$25.43") "00100100 00110010 00110101 00101110 00110100 00110011" >>> make_bitseq("~5") "01111110 00110101"
我們也可以是用python的f-string 來格式化,比如f"{ord(i):08b}":
冒號的左側是ord(i),它是實際的對象,其值將被格式化并插入到輸出中。 使用ord()為單個str字符提供了base-10代碼點。
冒號的右側是格式說明符。 08表示寬度為8,0填充,b用作在基數2(二進制)中輸出結果數的符號。
ASCII編碼不夠用了ASCII采用的是8bit來存儲字符(只使用7位,剩下的1位二進制為0),所以,ASCII最多存儲128個字符,這有個簡單的公式,計算存儲字符的bit數量與存儲字符總數的關系:2的n次方,n表示bit數量。例如:
1bit存儲2個字符
8bit存儲256個字符
64bit存儲2的64次方 == 18,446,744,073,709,551,616
我們可以寫個簡單的代碼,來計算一下,指定字符數量,至少需要多少bit來存儲:
>>> from math import ceil, log >>> def n_bits_required(nvalues: int) -> int: ... return ceil(log(nvalues) / log(2)) >>> n_bits_required(256) 8數字系統
在上面的ASCII討論中,您看到每個字符映射到0到127范圍內的整數。但在CPython中還有其他的數字系統,通過其他方式是表示數字。除了十進制外,python還支持以下幾個方式:
Binary: 2進制
Octal: 8進制
Hexadecimal (hex): 16進制
你可能要問,為什么有了十進制,還要支持這么多其他進制的數字了?這個取決你的業務場景和操作系統,在Python里,把str轉換成int,默認是10進制的。
>>> int("11") 11 >>> int("11", base=10) # 10 is already default 11 >>> int("11", base=2) # Binary 3 >>> int("11", base=8) # Octal 9 >>> int("11", base=16) # Hex 17
你可以在賦值時,直接告訴解釋器數字的類型,不同進制標表示方法如下:
類型 | 前綴 | 示例 |
---|---|---|
n/a | n/a | 11 |
二進制 | 0b 或者 0B | 0b11 |
八進制 | 0o 或者 0O | 0o11 |
十六進制 | 0x 或者 0X | 0x11 |
>>> 11 11 >>> 0b11 # 二進制 3 >>> 0o11 # 八進制 9 >>> 0x11 # 16進制 17深入Unicode
正如您所看到的,ASCII的問題在于它不是一個足夠大的字符集來容納世界上的語言,方言,符號和字形。 (這對于英語來說甚至都不夠大。)Unicode從根本上起到與ASCII相同的作用,但是Unicode擁有更大的存儲空間,具有1,114,112個可能的字符,能夠完全包含世界上所有的語言。事實上,ASCII是Unicode的完美子集。 Unicode表中的前128個字符與您合理期望的ASCII字符完全對應。
Unicode本身不是編碼,但是有很多遵循Unicode編碼規范編碼,后面講到的UTF-8就是其中一個。
Unicode vs UTF-8Unicode是一種抽象編碼標準,而不是編碼。這就是UTF-8和其他編碼方案發揮作用的地方。 Unicode標準(字符到代碼點的映射)從其單個字符集定義了幾種不同的編碼。UTF-8及其較少使用的表兄弟UTF-16和UTF-32是用于將Unicode字符表示為每個字符一個或多個字節的二進制數據的編碼格式。我們稍后將討論UTF-16和UTF-32,但到目前為止,UTF-8占據了最大份額。
Python 3里的編碼與解碼Python 3的str類型用于表示人類可讀的文本,可以包含任何Unicode字符。
相反,字節類型表示二進制數據或原始字節序列,它們本質上沒有附加編碼。
編碼和解碼是從一個到另一個的過程:
decode 和 encode 函數,默認編碼是utf-8:
>>> "résumé".encode("utf-8") b"rxc3xa9sumxc3xa9" >>> "El Ni?o".encode("utf-8") b"El Nixc3xb1o" >>> b"rxc3xa9sumxc3xa9".decode("utf-8") "résumé" >>> b"El Nixc3xb1o".decode("utf-8") "El Ni?o"
str.encode()的結果是一個bytes對象,bytes對象只允許ASCII字符。這就是為什么在調用“ElNi?o”.encode(“utf-8”)時,允許ASCII兼容的“El”按原樣表示,但帶有波浪號的n被轉義為“ xc3 xb1”。 這個看起來很亂的序列代表兩個字節,十六進制為0xc3和0xb1:
>>> " ".join(f"{i:08b}" for i in (0xc3, 0xb1)) "11000011 10110001"Python3一切字符皆Unicode
默認情況下,Python 3源代碼假定為UTF-8。 這意味著您不需要# - - 編碼:UTF-8 - - 位于Python 3中.py文件的頂部。
默認情況下,所有文本(str)都是Unicode。 編碼的Unicode文本表示為二進制數據(字節)。 str類型可以包含任何文字Unicode字符,例如“Δv/Δt”,所有這些字符都將存儲為Unicode。
Unicode字符集中的任何內容都是標識符中的猶太符號,這意味著résumé=“?/ Documents / resume.pdf”是有效的,雖然這看起來很花哨。
Python的re模塊默認為re.UNICODE標志而不是re.ASCII。 這意味著,例如,r“ w”匹配Unicode字符,而不僅僅是ASCII字母。
str.encode()和bytes.decode()中的默認編碼是UTF-8。
還有一個更細微的屬性,即內置的open()的默認編碼是依賴于平臺的,并且取決于locale.getpreferredencoding()的值:
>>> # Mac OS X High Sierra >>> import locale >>> locale.getpreferredencoding() "UTF-8" >>> # Windows Server 2012; other Windows builds may use UTF-16 >>> import locale >>> locale.getpreferredencoding() "cp1252"
一個關鍵特性是UTF-8是一種可變長度編碼。回想一下關于ASCII的部分。 擴展ASCII-land中的所有內容最多需要一個字節的空間。 您可以使用以下生成器表達式快速證明這一點:
>>> all(len(chr(i).encode("ascii")) == 1 for i in range(128)) True
UTF-8完全不同。 給定的Unicode字符可以占用1到4個字節。 以下是占用四個字節的單個Unicode字符的示例:
>>> ibrow = "
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/43897.html
摘要:每個字符都可以編碼為唯一的序列。但在中還有其他的數字系統,通過其他方式是表示數字。事實上,是的完美子集。里的編碼與解碼的類型用于表示人類可讀的文本,可以包含任何字符。編碼的文本表示為二進制數據字節。 概述 在使用Python或者其他的編程語言,都會多多少少遇到編碼錯誤,處理起來非常痛苦。在Stack Overflow和其他的編程問答網站上,UnicodeDecodeError和Unic...
摘要:相信很多人在格式化字符串的時候都用的語法,提出一種更先進的格式化方法并成為的標準用來替換舊的格式化語法,從開始已經實現了這一方法其它解釋器未考證。 showImg(https://segmentfault.com/img/remote/1460000018650325); 相信很多人在格式化字符串的時候都用%s % v的語法,PEP 3101 提出一種更先進的格式化方法 str.for...
摘要:最近使用處理一些網絡相關的問題,被相關的一系列編碼問題搞得一頭霧水。與接下來是中對于字符串的處理。中的和在中,其類型規定了底層的數據結構,是位整數串,也即跟語言中的字符串類似。這些問題在中得到解決。 最近使用 Python 2 處理一些網絡相關的問題,被 Unicode, String 相關的一系列編碼問題搞得一頭霧水。在這里整理一下相關的概念吧。 ASCII Unicode UTF8...
摘要:使用進行并發編程篇三掘金這是使用進行并發編程系列的最后一篇。所以我考慮啟用一個本地使用進行并發編程篇二掘金我們今天繼續深入學習。 使用 Python 進行并發編程 - asyncio 篇 (三) - 掘金 這是「使用Python進行并發編程」系列的最后一篇。我特意地把它安排在了16年最后一天。 重新實驗上篇的效率對比的實現 在第一篇我們曾經對比并發執行的效率,但是請求的是httpb...
摘要:縮進不一致,會導致運行錯誤。變量變量在使用前必須先定義即賦予變量一個值,否則會報錯數據類型布爾只有和兩個值,表示真或假。 簡介 Python 是一種高層次的結合了解釋性、編譯性、互動性和面向對象的腳本語言。Python 由 Guido van Rossum 于 1989 年底在荷蘭國家數學和計算機科學研究所發明,第一個公開發行版發行于 1991 年。 特點 易于學習:Python ...
閱讀 2265·2021-09-27 13:35
閱讀 561·2019-08-30 15:55
閱讀 810·2019-08-30 15:53
閱讀 555·2019-08-30 15:52
閱讀 2146·2019-08-30 12:59
閱讀 2269·2019-08-29 16:42
閱讀 1385·2019-08-26 18:26
閱讀 2467·2019-08-26 13:48