欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

關(guān)于Python編碼這一篇文章就夠了

系統(tǒng) 1997 0

概述

在使用Python或者其他的編程語(yǔ)言,都會(huì)多多少少遇到編碼錯(cuò)誤,處理起來(lái)非常痛苦。在Stack Overflow和其他的編程問(wèn)答網(wǎng)站上,UnicodeDecodeError和UnicodeEncodeError也經(jīng)常被提及。本篇教程希望能幫你認(rèn)識(shí)Python編碼,并能夠從容的處理編碼問(wèn)題。

本教程提到的編碼知識(shí)并不限定在Python,其他語(yǔ)言也大同小異,但我們依然會(huì)以Python為主,來(lái)演示和講解編碼知識(shí)。

通過(guò)該教程,你將學(xué)習(xí)到如下的知識(shí):

  • 獲取有關(guān)字符編碼和數(shù)字系統(tǒng)的概念
  • 理解編碼如何使用Python的str和bytes
  • 通過(guò)int函數(shù)了解Python對(duì)數(shù)字系統(tǒng)的支持
  • 熟悉Python字符編碼和數(shù)字系統(tǒng)相關(guān)的內(nèi)置函數(shù)

什么是字符編碼

現(xiàn)在的編碼規(guī)則已經(jīng)有好多了,最簡(jiǎn)單、最基本是的ASCII編碼,只要是你學(xué)過(guò)計(jì)算機(jī)相關(guān)的課程,你就應(yīng)該多少了解一點(diǎn)ASCII編碼,他是最小也是最適合了解字符編碼原理的編碼規(guī)則。具體如下:

  • 小寫(xiě)英文字符:a-z
  • 大寫(xiě)英文字符:A-Z
  • 符號(hào): 比如 $和!
  • 空白符:回車、換行、空格等
  • 一些不可打印的字符: 比如b等

那么,字符編碼的定義到底是什么了?它是一種將字符(如字母,標(biāo)點(diǎn)符號(hào),符號(hào),空格和控制字符)轉(zhuǎn)換為整數(shù)并最終轉(zhuǎn)換為bit進(jìn)行存儲(chǔ)的方法。 每個(gè)字符都可以編碼為唯一的bit序列。 如果你對(duì)bit的概念不了解,請(qǐng)不要擔(dān)心,我們后面會(huì)介紹。

ASCII碼的字符被分為如下幾組:

關(guān)于Python編碼這一篇文章就夠了_第1張圖片

ASCII表一共包括128個(gè)字符,如果你想了解整個(gè)ASCII表,這里有

Python string模塊

string模塊是python里處理字符串很方便的模塊,它包括了整個(gè)ASCII字符,讓我們來(lái)看看部分string模塊源碼:

          
            # From lib/python3.7/string.py

whitespace = ' \t\n\r\v\f'
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

學(xué)過(guò)計(jì)算機(jī)相關(guān)課程的同學(xué),應(yīng)該都知道,bit是計(jì)算機(jī)內(nèi)部存儲(chǔ)單位,只有0和1兩個(gè)狀態(tài)(二進(jìn)制),我們上面所說(shuō)的ASCII表,都是一個(gè)10進(jìn)制的數(shù)字表示一個(gè)字符,而這個(gè)10進(jìn)制數(shù)字,最終會(huì)轉(zhuǎn)換成0和1,存儲(chǔ)在計(jì)算機(jī)內(nèi)部。例如(第一列是10進(jìn)制數(shù)字,第二列是二進(jìn)制,第三列是計(jì)算機(jī)內(nèi)部存儲(chǔ)結(jié)果):

關(guān)于Python編碼這一篇文章就夠了_第2張圖片

這是一種在Python中將ASCII字符串表示為位序列的方便方法。 ASCII字符串中的每個(gè)字符都被偽編碼為8位,8位序列之間有空格,每個(gè)字符代表一個(gè)字符:

          
            >>> 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 來(lái)格式化,比如f"{ord(i):08b}":

  • 冒號(hào)的左側(cè)是ord(i),它是實(shí)際的對(duì)象,其值將被格式化并插入到輸出中。 使用ord()為單個(gè)str字符提供了base-10代碼點(diǎn)。
  • 冒號(hào)的右側(cè)是格式說(shuō)明符。 08表示寬度為8,0填充,b用作在基數(shù)2(二進(jìn)制)中輸出結(jié)果數(shù)的符號(hào)。

ASCII編碼不夠用了

ASCII采用的是8bit來(lái)存儲(chǔ)字符(只使用7位,剩下的1位二進(jìn)制為0),所以,ASCII最多存儲(chǔ)128個(gè)字符,這有個(gè)簡(jiǎn)單的公式,計(jì)算存儲(chǔ)字符的bit數(shù)量與存儲(chǔ)字符總數(shù)的關(guān)系:2的n次方,n表示bit數(shù)量。例如:

  • 1bit存儲(chǔ)2個(gè)字符
  • 8bit存儲(chǔ)256個(gè)字符
  • 64bit存儲(chǔ)2的64次方 == 18,446,744,073,709,551,616

我們可以寫(xiě)個(gè)簡(jiǎn)單的代碼,來(lái)計(jì)算一下,指定字符數(shù)量,至少需要多少bit來(lái)存儲(chǔ):

          
            >>> from math import ceil, log

>>> def n_bits_required(nvalues: int) -> int:
...     return ceil(log(nvalues) / log(2))

>>> n_bits_required(256)
8
          
        

數(shù)字系統(tǒng)

在上面的ASCII討論中,您看到每個(gè)字符映射到0到127范圍內(nèi)的整數(shù)。但在CPython中還有其他的數(shù)字系統(tǒng),通過(guò)其他方式是表示數(shù)字。除了十進(jìn)制外,python還支持以下幾個(gè)方式:

  • Binary: 2進(jìn)制
  • Octal: 8進(jìn)制
  • Hexadecimal (hex): 16進(jìn)制

你可能要問(wèn),為什么有了十進(jìn)制,還要支持這么多其他進(jìn)制的數(shù)字了?這個(gè)取決你的業(yè)務(wù)場(chǎng)景和操作系統(tǒng),在Python里,把str轉(zhuǎn)換成int,默認(rèn)是10進(jìn)制的。

          
            >>> 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
          
        

你可以在賦值時(shí),直接告訴解釋器數(shù)字的類型,不同進(jìn)制標(biāo)表示方法如下:

類型 前綴 示例
n/a n/a 11
二進(jìn)制 0b 或者 0B 0b11
八進(jìn)制 0o 或者 0O 0o11
十六進(jìn)制 0x 或者 0X 0x11
          
            >>> 11
11
>>> 0b11  # 二進(jìn)制
3
>>> 0o11  # 八進(jìn)制
9
>>> 0x11  # 16進(jìn)制
17
          
        

深入U(xiǎn)nicode

正如您所看到的,ASCII的問(wèn)題在于它不是一個(gè)足夠大的字符集來(lái)容納世界上的語(yǔ)言,方言,符號(hào)和字形。 (這對(duì)于英語(yǔ)來(lái)說(shuō)甚至都不夠大。)Unicode從根本上起到與ASCII相同的作用,但是Unicode擁有更大的存儲(chǔ)空間,具有1,114,112個(gè)可能的字符,能夠完全包含世界上所有的語(yǔ)言。事實(shí)上,ASCII是Unicode的完美子集。 Unicode表中的前128個(gè)字符與您合理期望的ASCII字符完全對(duì)應(yīng)。

Unicode本身不是編碼,但是有很多遵循Unicode編碼規(guī)范編碼,后面講到的UTF-8就是其中一個(gè)。

Unicode vs UTF-8

Unicode是一種抽象編碼標(biāo)準(zhǔn),而不是編碼。這就是UTF-8和其他編碼方案發(fā)揮作用的地方。 Unicode標(biāo)準(zhǔn)(字符到代碼點(diǎn)的映射)從其單個(gè)字符集定義了幾種不同的編碼。UTF-8及其較少使用的表兄弟UTF-16和UTF-32是用于將Unicode字符表示為每個(gè)字符一個(gè)或多個(gè)字節(jié)的二進(jìn)制數(shù)據(jù)的編碼格式。我們稍后將討論UTF-16和UTF-32,但到目前為止,UTF-8占據(jù)了最大份額。

Python 3里的編碼與解碼

Python 3的str類型用于表示人類可讀的文本,可以包含任何Unicode字符。

相反,字節(jié)類型表示二進(jìn)制數(shù)據(jù)或原始字節(jié)序列,它們本質(zhì)上沒(méi)有附加編碼。

編碼和解碼是從一個(gè)到另一個(gè)的過(guò)程:

關(guān)于Python編碼這一篇文章就夠了_第3張圖片

decode 和 encode 函數(shù),默認(rèn)編碼是utf-8:

          
            >>> "résumé".encode("utf-8")
b'r\xc3\xa9sum\xc3\xa9'
>>> "El Ni?o".encode("utf-8")
b'El Ni\xc3\xb1o'

>>> b"r\xc3\xa9sum\xc3\xa9".decode("utf-8")
'résumé'
>>> b"El Ni\xc3\xb1o".decode("utf-8")
'El Ni?o'
          
        

str.encode()的結(jié)果是一個(gè)bytes對(duì)象,bytes對(duì)象只允許ASCII字符。這就是為什么在調(diào)用“ElNi?o”.encode(“utf-8”)時(shí),允許ASCII兼容的“El”按原樣表示,但帶有波浪號(hào)的n被轉(zhuǎn)義為“ xc3 xb1”。 這個(gè)看起來(lái)很亂的序列代表兩個(gè)字節(jié),十六進(jìn)制為0xc3和0xb1:

          
            >>> " ".join(f"{i:08b}" for i in (0xc3, 0xb1))
'11000011 10110001'
          
        

Python3一切字符皆Unicode

  • 默認(rèn)情況下,Python 3源代碼假定為UTF-8。 這意味著您不需要# - - 編碼:UTF-8 - - 位于Python 3中.py文件的頂部。
  • 默認(rèn)情況下,所有文本(str)都是Unicode。 編碼的Unicode文本表示為二進(jìn)制數(shù)據(jù)(字節(jié))。 str類型可以包含任何文字Unicode字符,例如“Δv/Δt”,所有這些字符都將存儲(chǔ)為Unicode。
  • Unicode字符集中的任何內(nèi)容都是標(biāo)識(shí)符中的猶太符號(hào),這意味著résumé=“?/ Documents / resume.pdf”是有效的,雖然這看起來(lái)很花哨。
  • Python的re模塊默認(rèn)為re.UNICODE標(biāo)志而不是re.ASCII。 這意味著,例如,r“ w”匹配Unicode字符,而不僅僅是ASCII字母。
  • str.encode()和bytes.decode()中的默認(rèn)編碼是UTF-8。

還有一個(gè)更細(xì)微的屬性,即內(nèi)置的open()的默認(rèn)編碼是依賴于平臺(tái)的,并且取決于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'
          
        

一個(gè)關(guān)鍵特性是UTF-8是一種可變長(zhǎng)度編碼。回想一下關(guān)于ASCII的部分。 擴(kuò)展ASCII-land中的所有內(nèi)容最多需要一個(gè)字節(jié)的空間。 您可以使用以下生成器表達(dá)式快速證明這一點(diǎn):

          
            >>> all(len(chr(i).encode("ascii")) == 1 for i in range(128))
True
          
        

UTF-8完全不同。 給定的Unicode字符可以占用1到4個(gè)字節(jié)。 以下是占用四個(gè)字節(jié)的單個(gè)Unicode字符的示例:

          
            >>> ibrow = ""
>>> len(ibrow)
1
>>> ibrow.encode("utf-8")
b'\xf0\x9f\xa4\xa8'
>>> len(ibrow.encode("utf-8"))
4

>>> # Calling list() on a bytes object gives you
>>> # the decimal value for each byte
>>> list(b'\xf0\x9f\xa4\xa8')
[240, 159, 164, 168]
          
        

這是len()的一個(gè)微妙但重要的特性:

  • 作為Python str的單個(gè)Unicode字符的長(zhǎng)度始終為1,無(wú)論它占用多少字節(jié)。
  • 編碼為字節(jié)的相同字符的長(zhǎng)度將介于1和4之間。

UTF-16和UTF-32

我們來(lái)聊聊UTF-16和UTF-32,在實(shí)際的編程實(shí)踐中,它們和UTF-8區(qū)別還是很重要的,下面的通過(guò)實(shí)例我們來(lái)看看具體區(qū)別:

          
            >>> letters = "αβγδ"
>>> rawdata = letters.encode("utf-8")
>>> rawdata.decode("utf-8")
'αβγδ'
>>> rawdata.decode("utf-16")  # 
'????'
          
        

在這種情況下,使用UTF-8編碼四個(gè)希臘字母然后解碼回UTF-16中的文本將產(chǎn)生一個(gè)完全不同語(yǔ)言(韓語(yǔ))的文本str。
此表匯總了UTF-8,UTF-16和UTF-32下的字節(jié)范圍或字節(jié)數(shù):

編碼 長(zhǎng)度(字節(jié)) 是否可變
UTF-8 1~4
UTF-16 2~4
UTF-32 4

UTF系列編碼另外一個(gè)需要注意的地方是,UTF-8編碼占用存儲(chǔ)空間不一定比UTF-16少,因?yàn)樗麄兌疾皇枪潭ㄩL(zhǎng)度的。例如

          
            >>> text = "記者 鄭啟源 羅智堅(jiān)"
>>> len(text.encode("utf-8"))
26
>>> len(text.encode("utf-16"))
22
          
        

原因是U + 0800到U + FFFF(十進(jìn)制的2048到65535)范圍內(nèi)的代碼點(diǎn)占用了UTF-8中的三個(gè)字節(jié),而UTF-16中僅占用了兩個(gè)字節(jié)。
正常情況下,最好不用使用UTF-16,除非特殊要求,不然UTF-8更加通用。

Python內(nèi)建函數(shù)

Python內(nèi)置了很多與編碼相關(guān)的函數(shù):

  • ascii()
  • bin()
  • bytes()
  • chr()
  • hex()
  • int()
  • oct()
  • ord()
  • str()

可以分成以下幾組:

  • ascii(),bin(),hex()和oct(), 第一個(gè)是ascii(),它生成一個(gè)僅對(duì)象的ASCII表示,其中非ASCII字符被轉(zhuǎn)義。 其余三個(gè)分別給出整數(shù)的二進(jìn)制,十六進(jìn)制和八進(jìn)制表示。
  • bytes(),str()和int()是各自類型,bytes,str和int的類構(gòu)造函數(shù)。 它們各自提供了將輸入強(qiáng)制轉(zhuǎn)換為所需類型的方法。 例如,如前所述,雖然int(11.0)可能更常見(jiàn),但您可能也會(huì)看到int('11',base = 16)。
  • ord()和chr(),ord()將str字符轉(zhuǎn)換為10進(jìn)制,而chr()執(zhí)行相反的操作。

Python中的其他編碼

目前,我們講了4中編碼:

  • ASCII
  • UTF-8
  • UTF-16
  • UTF-32

還有其他很多編碼,比如Latin-1(也稱作ISO-8859-1),這是HTTP默認(rèn)的編碼,然而windows是Latin-1變體,稱作cp1252。
完整的已接受編碼列表隱藏在編解碼器模塊的文檔中,該模塊是Python標(biāo)準(zhǔn)庫(kù)的一部分。

還有一個(gè)有用的公認(rèn)編碼需要注意,即“unicode-escape”。 如果您有一個(gè)已解碼的str并希望快速獲得其轉(zhuǎn)義的Unicode文字的表示,那么您可以在.encode()中指定此編碼:

          
            >>> alef = chr(1575)  # Or "\u0627"
>>> alef_hamza = chr(1571)  # Or "\u0623"
>>> alef, alef_hamza
('?', '?')
>>> alef.encode("unicode-escape")
b'\\u0627'
>>> alef_hamza.encode("unicode-escape")
b'\\u0623'
          
        

注意外部數(shù)據(jù)編碼

雖然Python代碼默認(rèn)使用了UTF-8作為編碼,但并不意味著外部輸入的數(shù)據(jù)也是UTF-8編碼的,如果這些外部的數(shù)據(jù)沒(méi)有指定編碼,那么在處理他們是,你就要格外小心了。比如你調(diào)用API獲取數(shù)據(jù),正常是用UTF-8去解碼,沒(méi)有問(wèn)題,但如果突然API給你返回這樣的數(shù)據(jù):

          
            >>> data = b"\xbc cup of flour"
>>> data.decode("utf-8")
Traceback (most recent call last):
  File "
            
              ", line 1, in 
              
                
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 0: invalid start byte
              
            
          
        

這地方拋出了UnicodeDecodeError錯(cuò)誤,仔細(xì)檢查,發(fā)現(xiàn)其實(shí)數(shù)據(jù)的編碼是Latin-1。

          
            >>> data.decode("latin-1")
'? cup of flour'
          
        

如果你對(duì)字符串的編碼不確定,可以使用chardet庫(kù)來(lái)檢查字符串編碼。

總結(jié)

在本文中你已經(jīng)了解了編碼的詳細(xì)原理,相信你在以后的編程過(guò)程中,再遇到編碼錯(cuò)誤,相信你能比較從容的解決了。

翻譯自:原文地址
點(diǎn)擊獲取我的更多文章
關(guān)注我,獲取更多文章。
關(guān)于Python編碼這一篇文章就夠了_第4張圖片


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产成人在线观看免费网站 | 日韩在线小视频 | 成人性a激情免费视频 | 福利片在线看 | 久久久精 | 黄色一级在线视频 | 三更饺子1最刺激的一段整集 | 天天影院| 啪啪免费网站入口链接 | 26uuu在线观看 | 天天色综合天天 | 国产电影一区二区三区 | 国产在线第一区 | 国产毛片不卡 | 奇米影视888狠狠狠777不卡 | 99久久精品免费 | 91se在线看片国产免费观看 | 在线视频成人 | 亚洲在线视频网站 | 在线区 | 欧美1区| 天天操妹子 | 狠狠色依依成人婷婷九月 | 日本一区二区高清视频 | 丁香五月亚洲综合在线 | 亚洲欧洲视频在线观看 | 久久精品免费人成人A片 | 一区二区三区四区视频 | 六月丁香综合 | 中文字幕av在线播放 | 九九热视频这里只有精品 | 亚洲高清视频在线 | 亚洲二区视频 | 美女国产精品 | 国产精品一区二区三区99 | 久久国产精品一区二区 | 狠狠做深爱婷婷久久一区 | 欧美―第一页―浮力影院 | 国产成+人+亚洲+欧美+日韩 | 久草电影网站 | 久久国产免费观看精品 |