bytes對象,不可變的字節序列

2021-03-02 小菜學編程

不少程式語言中的 字符串 都是由 字符數組 (或稱為 字節序列 )來表示, C 語言就是這樣。

char msg[] = "Hello, world!";

由於一個字節最多只能表示 256 種字符,用來表示英文字符綽綽有餘,想覆蓋非英文字符便捉襟見肘了。為了表示眾多的非英文字符(比如漢字),計算機先驅們發明了 多字節編碼 ——通過多個字節來表示一個字符。由於原始字節序列不維護編碼信息,操作不慎便導致各種亂碼現象。

Python 提供的解決方案是 Unicode 字符串 ( str )對象, Unicode 可以表示各種字符,無需關心編碼。然而存儲或者網絡通訊時,字符串對象不可避免要 序列化 成字節序列。為此, Python 額外提供了字節序列對象 —— bytes 。

如上圖, str 對象統一表示一個 字符串 ,不需要關心編碼;計算機通過 字節序列 與存儲介質和網絡介質打交道,字節序列由 bytes 對象表示;存儲或傳輸 str 對象時,需要將其 序列化 成字節序列,序列化過程也是 編碼 的過程。

好了,我們已經弄明白 str 對象以 bytes 之間的關係,這兩者是 Python 中最重要的內建對象之一。讀者對 str 對象應該再熟悉不過了,但對更接近底層的 bytes 對象可能涉獵不多。沒關係,經過本節學習,你將徹底掌握它!

對象結構

bytes 對象用於表示由若干字節組成的 字節序列 以及相關的 操作 ,並不關心字節序列的 含義 。因此, bytes 應該是一種 變長對象 ,內部由 C 數組實現。Include/boolobject.h 頭文件中的定義印證了我們的猜測:

typedef struct {
    PyObject_VAR_HEAD
    Py_hash_t ob_shash;
    char ob_sval[1];

    /* Invariants:
     *     ob_sval contains space for 'ob_size+1' elements.
     *     ob_sval[ob_size] == 0.
     *     ob_shash is the hash of the string or -1 if not computed yet.
     */
} PyBytesObject;

字節序列對象 PyBytesObject 中,確實藏著一個字符數組 ob_sval 。注意到 ob_sval 數組長度定義為 1 ,這是 C 語言中定義 變長數組 的技巧。這個技巧在前面章節( int 對象,永不溢出的整數 )中介紹過,這裡不再贅述。源碼注釋表明, Python 為待存儲的字節序列額外分配一個字節,用於在末尾處保存 \0 ,以便兼容 C 字符串。

此外,我們還留意到另一個欄位 ob_shash ,它用於保存字節序列的 哈希值 。Python 對象哈希值應用範圍很廣,比如 dict 字典對象依賴對象哈希值進行存儲。由於計算 bytes 對象哈希值需要遍歷其內部的字符數組,開銷相對較大。因此, Python 選擇將哈希值保存起來,以空間換時間,避免重複計算。

最後,以幾個典型例子結束 bytes 對象結構介紹,以此加深理解:

由此可見,就算空 bytes 對象( b'' )也是要佔用內存空間的,至少變長對象 公共頭部 是少不了的。

>>> sys.getsizeof(b'')
33

bytes 對象佔用的內存空間可分為以下個部分進行計算:

變長對象公共頭部 24 字節,ob_refcnt 、 ob_type 、 ob_size 每個欄位各佔用 8 字節;

因此, bytes 對象空間計算公式為

學習了 bytes 對象的結構,接下來我們還會探索 bytes 對象的行為以及 python 是如何利用 字節緩衝池 來優化單字節 bytes 對象(也可稱為 字符對象 )的創建效率。點擊 「閱讀原文」,獲取更多細節!

😘  原創不易,求贊,求在看

相關焦點

  • python基礎-bytes和bytearray的用法
    Python中的序列類型有bytes和bytearray。二進位序列類型的用法比較少見,是python中少用的一種序列類型,對於二進位序列類型,大家基本了解即可。bytes二進位序列類型指定長度的零填充字節對象: bytes(3)二進位字符串對象:bytes(b'abc')bytearray二進位數組指定長度的零填充字節對象: bytearray(3)二進位字符串對象:bytearray(b'abc')實例:print(type("ffff
  • Python bytes類型及用法
    bytes 是 Python 3.x 新增的類型,在 Python 2.x 中是不存在的。字節串(bytes)和字符串(string)的對比:字符串由若干個字符組成,以字符為單位進行操作;字節串由若干個字節組成,以字節為單位進行操作。字節串和字符串除了操作的數據單元不同之外,它們支持的所有方法都基本相同。
  • Python高效編程之88條軍規(1):編碼規範、字節序列與字符串
    例如,為了從bar包導入foo模塊,應該使用from bar import foo,而不要使用Import foo;(3)如果必須要使用相對的模塊名,應該顯式使用from . import foo形式;軍規2:了解字節序列(bytes)和字符串(str)的差異在Python語言中,有兩個數據類型可以表示字符序列:字節序列和字符串。
  • Python 的 bytes轉 str
    原來的規範允許長達6位元組的序列,可以覆蓋到31位(通用字符集原來的極限)。儘管如此,2003年11月UTF-8被RFC 3629重新規範,只能使用原來Unicode定義的區域,U+0000到U+10FFFF。
  • Fluent Python - Part2 序列構成的數組
    通過了解 Python 不同的序列類型以及它們的使用,能夠讓我們避免重複發明輪子,而且 Python 的 API 能夠幫助我們把自己定義的結構設計得跟原生序列一樣。序列類型根據是否能放不同類型的數據分類容器序列:能存放不同類型的數據,存放的是對象的引用。其中包括: list, tuple, collections.deque等。
  • Deno bytes 模塊全解析
    來源:https://www.zhihu.com/question/30401979語法new ArrayBuffer(length)參數:length 表示要創建的 ArrayBuffer 的大小,單位為字節。返回值:一個指定大小的 ArrayBuffer 對象,其內容被初始化為 0。
  • Python 3中str與bytes的區分
    文本總是Unicode,由str類型表示,二進位數據則由bytes類型表示。Python 3不會以任意隱式的方式混用str和bytes,正是這使得兩者的區分特別清晰。你不能拼接字符串和字節包,也無法在字節包裡搜索字符串(反之亦然),也不能將字符串傳入參數為字節包的函數(反之亦然)。這是件好事。
  • 計算機英語:位與字節(Bits & Bytes)
    KB = kilobyte = about 1,000 (one thousand) bytes, (1024 or 2^10)   MB = megabyte = about 1,000,000 (one million) bytes, (1,048,576 or 2^20)   GB= gigabyte = about
  • Golang 語言標準庫 bytes 包怎麼使用?
    其中 byte 是 uint8 的別名,表示 ASCII 碼的一個字符,佔用 1 個字節,rune 是 int32 的別名,表示 UTF-8 字符,佔用 4 個字節。[]byte 表示字節切片,因為字符串也可以表示為字節切片,所以 bytes 包的函數和 strings 包的函數比較相似。
  • Fluent Python - Part4 文本和字節序列
    人類使用文本,計算機使用字節序列--- Esther Nam 和 Travis Fischer本章內容基本沒啥用,平常也基本接觸不到多編碼類型的文本處理
  • python3 還原bytes為中文的折騰
    linux默認使用utf-8編碼,而utf-8默認以unicode字符集進行的編碼,此種格式其實是一種utf-8的字節碼[bytes]。如果要還原,需要對其進行utf-8解碼這次知道是啥了,那就知道要怎麼處理了,python中有很多方法可以編碼、解碼,於是開始第二個過程二、怎麼還原成中文?
  • 【SQL】序列SEQUENCE
    定義序列是可以生成唯一序列值的用戶對象,通常用於主鍵和unique約束,可以使用這些偽列引用 SQL 語句中的序列值A sequence
  • Python基礎教程(一) - 序列:字符串、列表和元組
    這一章我們主要研究這樣一些類型,他們的成員是有序排列的,並且可以通過下標偏移量訪問的,這類Python類型統稱為序列,包括字符串、列表和元組。序列類型操作符成員關係操作符(in、not in):成員關係操作符是用來判斷一個元素是否屬於一個序列的。
  • STM32之option bytes踩坑記錄
    後來查了些資料才發現:STM32的獨立看門狗可以是硬體使能或軟體使能,硬體使能是通過option bytes配置,軟體使能是通過軟體設置寄存器位配置。如果啟用了硬體使能,必須通過擦除相應的選擇字節位關閉硬體看門狗功能,這時看門狗的功能可以通過軟體使能。