淺析Python3中的bytes和str類型

来源:https://www.cnblogs.com/djdjdj123/archive/2019/11/08/11822837.html
-Advertisement-
Play Games

Python 3最重要的新特性之一是對字元串和二進位數據流做了明確的區分。文本總是Unicode,由str類型表示,二進位數據則由bytes類型表示。Python 3不會以任意隱式的方式混用str和bytes,你不能拼接字元串和位元組流,也無法在位元組流里搜索字元串(反之亦然),也不能將字元串傳入參數為 ...


Python 3最重要的新特性之一是對字元串和二進位數據流做了明確的區分。文本總是Unicode,由str類型表示,二進位數據則由bytes類型表示。Python 3不會以任意隱式的方式混用str和bytes,你不能拼接字元串和位元組流,也無法在位元組流里搜索字元串(反之亦然),也不能將字元串傳入參數為位元組流的函數(反之亦然)。

下麵讓我們深入分析一下二者的區別和聯繫。

編碼發展的歷史

在談bytes和str之前,需要先說說關於編碼是如何發展的。。

在電腦歷史的早期,美國為代表的英語系國家主導了整個電腦行業,26個英文字母組成了多樣的英語單詞、語句、文章。因此,最早的字元編碼規範是ASCII碼,一種8位即1個位元組的編碼規範,它可以涵蓋整個英語系的編碼需要。

編碼是什麼?編碼就是把一個字元用一個二進位來表示。我們都知道,所有的東西,不管是英文、中文還是符號等等,最終存儲在磁碟上都是01010101這類東西。在電腦內部,讀取和存儲數據歸根結底,處理的都是0和1組成的比特流。問題來了,人類看不懂這些比特流,如何讓這些010101對人類變得可讀呢?於是出現了字元編碼,它是個翻譯機,在電腦內部某個地方,透明的幫我們將比特流翻譯成人類可以直接理解的文字。對於一般用戶,不需要知道這個過程是什麼原理,是怎麼執行的。但是對於程式員卻是個必須搞清楚的問題。

以ASCII編碼為例,它規定1個位元組8個比特位代表1個字元的編碼,也就是“00000000”這麼寬,一個一個位元組的解讀。例如:01000001表示大寫字母A,有時我們會“偷懶"的用65這個十進位來表示A在ASCII中的編碼。8個比特位,可以沒有重覆的最多表示2的8次方(255)個字元。

後來,電腦得到普及,中文、日文、韓文等等國家的文字需要在電腦內表示,ASCII的255位遠遠不夠,於是標準組織制定出了叫做UNICODE的萬國碼,它規定任何一個字元(不管哪國的)至少以2個位元組表示,可以更多。其中,英文字母就是用2個位元組,而漢字是3個位元組。這個編碼雖然很好,滿足了所有人的要求,但是它不相容ASCII,同時還占用較多的空間和記憶體。因為,在電腦世界更多的字元是英文字母,明明可以1個位元組就能夠表示,非要用2個。

於是UTF-8編碼應運而生,它規定英文字母系列用1個位元組表示,漢字用3個位元組表示等等。因此,它相容ASCII,可以解碼早期的文檔。UTF-8很快就得到了廣泛的應用。

在編碼的發展歷程中,我國還創造了自己的編碼方式,例如GBK,GB2312,BIG5。他們只局限於在國內使用,不被國外認可。在GBK編碼中,中文漢字占2個位元組。

bytes和str之間的異同
回到bytes和str的身上。bytes是一種比特流,它的存在形式是01010001110這種。我們無論是在寫代碼,還是閱讀文章的過程中,肯定不會有人直接閱讀這種比特流,它必須有一個編碼方式,使得它變成有意義的比特流,而不是一堆晦澀難懂的01組合。因為編碼方式的不同,對這個比特流的解讀也會不同,對實際使用造成了很大的困擾。下麵讓我們看看Python是如何處理這一系列編碼問題的:

>>> s = "中文"
>>> s
'中文'
>>> type(s)
<class 'str'>
>>> b = bytes(s, encoding='utf-8')
>>> b
b'\xe4\xb8\xad\xe6\x96\x87'
>>> type(b)
<class 'bytes'>

從例子可以看出,s是個字元串類型。Python有個內置函數bytes()可以將字元串str類型轉換成bytes類型,b實際上是一串01的組合,但為了在ide環境中讓我們相對直觀的觀察,它被表現成了b'\xe4\xb8\xad\xe6\x96\x87'這種形式,開頭的b表示這是一個bytes類型。\xe4是十六進位的表示方式,它占用1個位元組的長度,因此”中文“被編碼成utf-8後,我們可以數得出一共用了6個位元組,每個漢字占用3個,這印證了上面的論述。在使用內置函數bytes()的時候,必須明確encoding的參數,不可省略。

我們都知道,字元串類str里有一個encode()方法,它是從字元串向比特流的編碼過程。而bytes類型恰好有個decode()方法,它是從比特流向字元串解碼的過程。除此之外,我們查看Python源碼會發現bytes和str擁有幾乎一模一樣的方法列表,最大的區別就是encode和decode。

從實質上來說,字元串在磁碟上的保存形式也是01的組合,也需要編碼解碼。

如果,上面的闡述還不能讓你搞清楚兩者的區別,那麼記住下麵兩幾句話:

  1. 在將字元串存入磁碟和從磁碟讀取字元串的過程中,Python自動地幫你完成了編碼和解碼的工作,你不需要關心它的過程。

  2. 使用bytes類型,實質上是告訴Python,不需要它幫你自動地完成編碼和解碼的工作,而是用戶自己手動進行,並指定編碼格式。

  3. Python已經嚴格區分了bytes和str兩種數據類型,你不能在需要bytes類型參數的時候使用str參數,反之亦然。這點在讀寫磁碟文件時容易碰到。

在bytes和str的互相轉換過程中,實際就是編碼解碼的過程,必須顯式地指定編碼格式。

>>> b
b'\xe4\xb8\xad\xe6\x96\x87'
>>> type(b)
<class 'bytes'>
>>> s1 = str(b)
>>> s1
"b'\\xe4\\xb8\\xad\\xe6\\x96\\x87'"
>>> type(s1)
<class 'str'>
>>> s1 = str(b, encoding='utf-8')
>>> s1
'中文'
>>> type(s1)
<class 'str'>

我們再把字元串s1,轉換成gbk編碼的bytes類型:

>>> s1
'中文'
>>> type(s1)
<class 'str'>
>>> b =  bytes(s1, encoding='gbk')
>>> b
b'\xd6\xd0\xce\xc4'

轉自:https://www.cnblogs.com/chownjy/p/6625299.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 字元串或串(String)是由數字、字母、下劃線組成的一串字元。一般記為 s=“a1a2···an”(n>=0)。它是編程語言中表示文本的數據類型。在程式設計中,字元串(string)為符號或數值的一個連續序列,如符號串(一串字元)或二進位數字串(一串二進位數字)。 String類型你一定不陌生,畢 ...
  • 我們知道,swoole中有兩大進程,分別是 master 主進程和 manager 管理進程。 其中 master 主進程中會有一個主 reactor 線程和多個 reactor 線程,主要的作用就是用來維護TCP連接,處理網路IO,收發數據。 而 manager 管理進程,作用則是 fork 和管 ...
  • 1. random模塊 導入的是random模塊,格式是: import random 1.1 隨機小數 取隨機小數 : 數學計算。 print(random.random()) # 取0-1之間的小數print(random.uniform(1,2)) # 取1-2之間的小數 1.2 隨機整數 取 ...
  • 一、阻塞隊列:用於保存等待執行的任務。在阻塞隊列中,線程阻塞的兩種情況: 1.當隊列中沒有數據的情況下,消費者端的所有線程都會被自動阻塞(掛起),直到有數據放入隊列。 2.當隊列中填滿數據的情況下, 生產者端的所有線程都會被自動阻塞,知道隊列中有空位置,線程被自動喚醒。 二、阻塞隊列的主要方法 拋出 ...
  • 一、實習內容 選擇一個調度演算法,實現處理器調度。 二、實習目的 在採用多道程式設計的系統中,往往有若幹個進程同時處於就緒狀態。當就緒進程個數大於處理器數時,就必須依照某種策略來決定哪些進程優先占用處理器。本實習模擬在單處理器情況下的處理器調度,幫助學生加深瞭解處理器調度的工作。 三、實習題目 本實習 ...
  • Python實戰教程,用Python做列印日曆的小程式,使用者可以通過輸入年月信息,程式將會輸出這個月的日曆 ...
  • 首先來總結一下,ArrayList的一些特點: 1.arraylist本質上就是一個elementData數組,它允許對元素進行快速隨機訪問,可以存放null值; 2.arraylist區別於數組的地方在於能夠自動擴展大小,其中關鍵就是grow() 方法,每次擴充後數組為原來數組的1.5倍; 3.a ...
  • 前言 array,顧名思義,數組,就是存儲數字、處理數字的一種數據結構。今天在將list轉換為array時,遇到了一個問題,數據量比較大,剛開始怎麼都不知道問題出在哪裡。直到我用一個3 3的小數據測試時,才發現問題的本質所在。浪費了半天的時間,不過總算搞明白了。 學的不夠踏實,以此警戒所有的初學者: ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...