內建型別¶
以下章節描述瞭解釋器內建的標準型別。
主要的內建型別有數字、序列、對映、類、例項和異常。
一些集合類是可變的。原地新增、刪除或重新排列其成員,並且不返回特定項的方法,永遠不會返回集合例項本身,而是返回 None
。
一些操作由多個物件型別支援;特別是,實際上所有物件都可以比較是否相等、測試真值,並轉換為字串(使用 repr()
函式或略有不同的 str()
函式)。當物件被 print()
函式寫入時,會隱式使用後一個函式。
真值檢測¶
任何物件都可以進行真值測試,以便在 if
或 while
條件中使用,或者作為以下布林運算的運算元。
預設情況下,一個物件被認為是真,除非它的類定義了一個 __bool__()
方法返回 False
或一個 __len__()
方法返回零,當使用物件呼叫時。[1] 以下是大多數被認為是假的內建物件
定義為假的常量:
None
和False
任何數字型別的零:
0
、0.0
、0j
、Decimal(0)
、Fraction(0, 1)
空序列和集合:
''
、()
、[]
、{}
、set()
、range(0)
具有布林結果的運算和內建函式總是返回 0
或 False
表示假,返回 1
或 True
表示真,除非另有說明。(重要例外:布林運算 or
和 and
總是返回它們的運算元之一。)
布林運算 — and
、or
、not
¶
以下是布林運算,按優先順序升序排列
運算 |
結果 |
備註 |
---|---|---|
|
如果 x 為真,則為 x,否則為 y |
(1) |
|
如果 x 為假,則為 x,否則為 y |
(2) |
|
如果 x 為假,則為 |
(3) |
備註
這是一個短路運算子,因此它僅在第一個引數為假時才計算第二個引數。
這是一個短路運算子,因此它僅在第一個引數為真時才計算第二個引數。
not
的優先順序低於非布林運算子,因此not a == b
被解釋為not (a == b)
,而a == not b
是語法錯誤。
比較¶
Python 中有八種比較操作。它們都具有相同的優先順序(高於布林運算的優先順序)。比較操作可以任意連結;例如,x < y <= z
等價於 x < y and y <= z
,不同之處在於 y 只會被計算一次(但在兩種情況下,當發現 x < y
為假時,z 都不會被計算)。
下表總結了比較操作。
運算 |
含義 |
---|---|
|
嚴格小於 |
|
小於或等於 |
|
嚴格大於 |
|
大於或等於 |
|
等於 |
|
不等於 |
|
物件標識 |
|
取反的物件標識 |
不同型別的物件,除了不同的數值型別外,永遠不會比較相等。==
運算子總是被定義,但對於某些物件型別(例如,類物件),它等價於 is
。<
、<=
、>
和 >=
運算子僅在有意義的情況下定義;例如,當其中一個引數是複數時,它們會引發 TypeError
異常。
除非類定義了 __eq__()
方法,否則類的非相同例項通常比較為不相等。
除非類定義了足夠的方法 __lt__()
、 __le__()
、__gt__()
和 __ge__()
(一般來說,如果希望比較運算子具有常規含義,則 __lt__()
和 __eq__()
就足夠了),否則無法對一個類的例項與同一類的其他例項或其它型別的物件進行排序。
is
和 is not
運算子的行為無法自定義; 此外,它們可以應用於任何兩個物件,並且永遠不會引發異常。
另外兩個具有相同語法優先順序的操作 in
和 not in
被支援 可迭代 的型別或者實現了 __contains__()
方法的型別。
數值型別 — int
, float
, complex
¶
有三種不同的數值型別:整數、浮點數 和 複數。此外,布林值是整數的子型別。整數具有無限的精度。浮點數通常使用 C 中的 double 實現;有關執行您的程式的計算機的浮點數的精度和內部表示的資訊,請參閱 sys.float_info
。複數有一個實部和一個虛部,它們都是浮點數。要從複數 z 中提取這些部分,請使用 z.real
和 z.imag
。(標準庫包括其他數值型別 fractions.Fraction
(用於有理數)和 decimal.Decimal
(用於具有使用者可定義精度的浮點數)。)
數字由數字字面量或作為內建函式和運算子的結果建立。未修飾的整數文字(包括十六進位制、八進位制和二進位制數)產生整數。包含小數點或指數符號的數字文字產生浮點數。將 'j'
或 'J'
附加到數字文字會產生一個虛數(實部為零的複數),您可以將其新增到整數或浮點數以獲得具有實部和虛部的複數。
Python 完全支援混合算術:當二元算術運算子具有不同數值型別的運算元時,型別較“窄”的運算元會擴充套件到另一個運算元的型別,其中整數比浮點數窄,浮點數比複數窄。不同型別數字之間的比較行為就像比較這些數字的精確值一樣。[2]
建構函式 int()
、float()
和 complex()
可用於生成特定型別的數字。
所有數值型別(複數除外)都支援以下操作(有關操作的優先順序,請參閱 運算子優先順序)
運算 |
結果 |
備註 |
完整文件 |
---|---|---|---|
|
x 和 y 的和 |
||
|
x 和 y 的差 |
||
|
x 和 y 的乘積 |
||
|
x 和 y 的商 |
||
|
x 和 y 的向下取整的商 |
(1)(2) |
|
|
|
(2) |
|
|
x 的負數 |
||
|
x 不變 |
||
|
x 的絕對值或大小 |
||
|
x 轉換為整數 |
(3)(6) |
|
|
x 轉換為浮點數 |
(4)(6) |
|
|
實部為 re,虛部為 im 的複數。im 預設為零。 |
(6) |
|
|
複數 c 的共軛 |
||
|
對 |
(2) |
|
|
x 的 y 次冪 |
(5) |
|
|
x 的 y 次冪 |
(5) |
備註
也稱為整數除法。對於
int
型別的運算元,結果的型別為int
。對於float
型別的運算元,結果的型別為float
。通常,結果是一個整數,儘管結果的型別不一定是int
。結果總是向負無窮舍入:1//2
是0
,(-1)//2
是-1
,1//(-2)
是-1
,而(-1)//(-2)
是0
。不適用於複數。如果適用,請使用
abs()
將其轉換為浮點數。從
float
到int
的轉換會截斷小數部分。有關其他轉換,請參閱函式math.floor()
和math.ceil()
。float 也接受字串“nan”和“inf”,以及可選的字首“+”或“-”,分別表示非數字 (NaN) 和正無窮或負無窮。
Python 將
pow(0, 0)
和0 ** 0
定義為1
,這在程式語言中很常見。接受的數字字面量包括數字
0
到9
或任何 Unicode 等效字元(具有Nd
屬性的程式碼點)。有關具有
Nd
屬性的程式碼點的完整列表,請參閱 Unicode 標準。
所有 numbers.Real
型別(int
和 float
)還包括以下操作
運算 |
結果 |
---|---|
x 截斷為 |
|
x 四捨五入到 n 位數字,四捨五入到最接近的偶數。如果省略 n,則預設為 0。 |
|
小於等於 x 的最大 |
|
大於等於 x 的最小 |
整數型別的位運算¶
位運算僅對整數有意義。位運算的結果計算方式如同在帶有無限個符號位的二進位制補碼中執行一樣。
二進位制位運算的優先順序都低於數值運算,高於比較運算;一元運算 ~
與其他一元數值運算(+
和 -
)具有相同的優先順序。
下表列出了按優先順序升序排序的位運算
運算 |
結果 |
備註 |
---|---|---|
|
x 和 y 的按位或 |
(4) |
|
x 和 y 的按位異或 |
(4) |
|
x 和 y 的按位與 |
(4) |
|
x 左移 n 位 |
(1)(2) |
|
x 右移 n 位 |
(1)(3) |
|
x 的位反轉 |
備註
負移位數是非法的,會導致引發
ValueError
。左移 n 位等同於乘以
pow(2, n)
。右移 n 位等同於整除以
pow(2, n)
。在有限的二進位制補碼錶示中使用至少一個額外的符號擴充套件位進行這些計算(工作位寬為
1 + max(x.bit_length(), y.bit_length())
或更多)足以獲得與存在無限個符號位時相同的結果。
整數型別的其他方法¶
int 型別實現了 numbers.Integral
抽象基類。此外,它還提供了一些其他方法
- int.bit_length()¶
返回用二進位制表示整數所需的位數,不包括符號和前導零
>>> n = -37 >>> bin(n) '-0b100101' >>> n.bit_length() 6
更準確地說,如果
x
非零,則x.bit_length()
是唯一的正整數k
,使得2**(k-1) <= abs(x) < 2**k
。等效地,當abs(x)
足夠小以具有正確舍入的對數時,則k = 1 + int(log(abs(x), 2))
。如果x
為零,則x.bit_length()
返回0
。等效於
def bit_length(self): s = bin(self) # binary representation: bin(-37) --> '-0b100101' s = s.lstrip('-0b') # remove leading zeros and minus sign return len(s) # len('100101') --> 6
在 3.1 版本中新增。
- int.bit_count()¶
返回整數絕對值的二進位制表示中 1 的個數。這也稱為人口計數。示例
>>> n = 19 >>> bin(n) '0b10011' >>> n.bit_count() 3 >>> (-n).bit_count() 3
等效於
def bit_count(self): return bin(self).count("1")
在 3.10 版本中新增。
- int.to_bytes(length=1, byteorder='big', *, signed=False)¶
返回表示整數的位元組陣列。
>>> (1024).to_bytes(2, byteorder='big') b'\x04\x00' >>> (1024).to_bytes(10, byteorder='big') b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' >>> (-1024).to_bytes(10, byteorder='big', signed=True) b'\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00' >>> x = 1000 >>> x.to_bytes((x.bit_length() + 7) // 8, byteorder='little') b'\xe8\x03'
整數使用 length 個位元組表示,預設為 1。如果整數無法用給定的位元組數表示,則會引發
OverflowError
。byteorder 引數決定用於表示整數的位元組順序,預設為
"big"
。如果 byteorder 為"big"
,則最高有效位元組位於位元組陣列的開頭。如果 byteorder 為"little"
,則最高有效位元組位於位元組陣列的末尾。signed 引數決定是否使用二進位制補碼來表示整數。如果 signed 為
False
並且給定的整數為負數,則會引發OverflowError
。signed 的預設值為False
。預設值可以方便地將整數轉換為單位元組物件。
>>> (65).to_bytes() b'A'
但是,當使用預設引數時,不要嘗試轉換大於 255 的值,否則會得到一個
OverflowError
。等效於
def to_bytes(n, length=1, byteorder='big', signed=False): if byteorder == 'little': order = range(length) elif byteorder == 'big': order = reversed(range(length)) else: raise ValueError("byteorder must be either 'little' or 'big'") return bytes((n >> i*8) & 0xff for i in order)
3.2 版本新增。
3.11 版本更改: 為
length
和byteorder
添加了預設引數值。
- classmethod int.from_bytes(bytes, byteorder='big', *, signed=False)¶
返回給定位元組陣列表示的整數。
>>> int.from_bytes(b'\x00\x10', byteorder='big') 16 >>> int.from_bytes(b'\x00\x10', byteorder='little') 4096 >>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=True) -1024 >>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=False) 64512 >>> int.from_bytes([255, 0, 0], byteorder='big') 16711680
引數 bytes 必須是 bytes-like object 或產生位元組的可迭代物件。
byteorder 引數決定用於表示整數的位元組順序,預設為
"big"
。如果 byteorder 為"big"
,則最高有效位元組在位元組陣列的開頭。如果 byteorder 為"little"
,則最高有效位元組在位元組陣列的末尾。要請求主機系統的本機位元組順序,請使用sys.byteorder
作為位元組順序值。signed 引數指示是否使用二進位制補碼來表示整數。
等效於
def from_bytes(bytes, byteorder='big', signed=False): if byteorder == 'little': little_ordered = list(bytes) elif byteorder == 'big': little_ordered = list(reversed(bytes)) else: raise ValueError("byteorder must be either 'little' or 'big'") n = sum(b << i*8 for i, b in enumerate(little_ordered)) if signed and little_ordered and (little_ordered[-1] & 0x80): n -= 1 << 8*len(little_ordered) return n
3.2 版本新增。
3.11 版本更改: 為
byteorder
添加了預設引數值。
- int.as_integer_ratio()¶
返回一對整數,其比率等於原始整數,且分母為正數。整數(整數)的比率始終為分子上的整數,分母為
1
。3.8 版本新增。
- int.is_integer()¶
返回
True
。為了與float.is_integer()
實現鴨子型別相容性而存在。3.12 版本新增。
浮點數的附加方法¶
float 型別實現了 numbers.Real
抽象基類。float 還有以下附加方法。
- float.as_integer_ratio()¶
返回一對整數,其比率正好等於原始浮點數。該比率處於最簡形式,並且具有正分母。在無窮大時引發
OverflowError
,在 NaN 時引發ValueError
。
- float.is_integer()¶
如果 float 例項是具有整數值的有限數,則返回
True
,否則返回False
。>>> (-2.0).is_integer() True >>> (3.2).is_integer() False
有兩個方法支援與十六進位制字串之間的轉換。由於 Python 的浮點數在內部儲存為二進位制數,因此將浮點數轉換為十進位制字串或從十進位制字串轉換通常會涉及小的舍入誤差。相比之下,十六進位制字串允許精確表示和指定浮點數。這在除錯和數值工作中非常有用。
- float.hex()¶
返回浮點數作為十六進位制字串的表示形式。對於有限的浮點數,此表示形式始終包含前導
0x
和尾隨p
和指數。
- classmethod float.fromhex(s)¶
類方法,用於返回由十六進位制字串 s 表示的浮點數。字串 s 可以包含前導和尾隨空格。
請注意,float.hex()
是一個例項方法,而 float.fromhex()
是一個類方法。
十六進位制字串採用以下形式
[sign] ['0x'] integer ['.' fraction] ['p' exponent]
其中可選的 sign
可以是 +
或 -
,integer
和 fraction
是十六進位制數字字串,exponent
是一個十進位制整數,帶有可選的前導符號。大小寫不重要,並且整數或小數部分中必須至少有一個十六進位制數字。此語法類似於 C99 標準的 6.4.4.2 節中指定的語法,也類似於 Java 1.5 及更高版本中使用的語法。特別是,float.hex()
的輸出可用作 C 或 Java 程式碼中的十六進位制浮點文字,而 C 的 %a
格式字元或 Java 的 Double.toHexString
生成的十六進位制字串被 float.fromhex()
接受。
請注意,指數以十進位制而不是十六進位制寫入,並且它給出了係數乘以的 2 的冪。例如,十六進位制字串 0x3.a7p10
表示浮點數 (3 + 10./16 + 7./16**2) * 2.0**10
,即 3740.0
。
>>> float.fromhex('0x3.a7p10')
3740.0
將反向轉換應用於 3740.0
會產生不同的十六進位制字串,該字串表示相同的數字
>>> float.hex(3740.0)
'0x1.d380000000000p+11'
數值型別的雜湊¶
對於數字 x
和 y
,可能具有不同的型別,要求當 x == y
時,始終有 hash(x) == hash(y)
(有關更多詳細資訊,請參閱 __hash__()
方法文件)。為了在各種數值型別(包括 int
,float
,decimal.Decimal
和 fractions.Fraction
)中易於實現和提高效率,Python 的數值型別雜湊基於單個數學函式,該函式定義為任何有理數,因此適用於 int
和 fractions.Fraction
的所有例項,以及 float
和 decimal.Decimal
的所有有限例項。本質上,此函式由對固定素數 P
取模的簡化給出。P
的值作為 modulus
屬性提供給 Python,該屬性是 sys.hash_info
的一部分。
CPython 實現細節: 當前,使用的素數在具有 32 位 C 長整數的機器上為 P = 2**31 - 1
,在具有 64 位 C 長整數的機器上為 P = 2**61 - 1
。
以下是詳細規則
如果
x = m / n
是一個非負有理數,且n
不能被P
整除,則定義hash(x)
為m * invmod(n, P) % P
,其中invmod(n, P)
表示n
對P
的模逆。如果
x = m / n
是一個非負有理數,且n
可以被P
整除(但m
不能),那麼n
沒有對P
的模逆,因此上面的規則不適用;在這種情況下,定義hash(x)
為常量值sys.hash_info.inf
。如果
x = m / n
是一個負有理數,則定義hash(x)
為-hash(-x)
。如果得到的雜湊值為-1
,則將其替換為-2
。特定的值
sys.hash_info.inf
和-sys.hash_info.inf
分別用作正無窮和負無窮的雜湊值。對於一個
complex
數字z
,實部和虛部的雜湊值透過計算hash(z.real) + sys.hash_info.imag * hash(z.imag)
來組合,並對2**sys.hash_info.width
取模,使其位於range(-2**(sys.hash_info.width - 1), 2**(sys.hash_info.width - 1))
範圍內。同樣,如果結果為-1
,則將其替換為-2
。
為了澄清上述規則,這裡有一些示例 Python 程式碼,它等效於內建的雜湊函式,用於計算有理數、float
或 complex
的雜湊值。
import sys, math
def hash_fraction(m, n):
"""Compute the hash of a rational number m / n.
Assumes m and n are integers, with n positive.
Equivalent to hash(fractions.Fraction(m, n)).
"""
P = sys.hash_info.modulus
# Remove common factors of P. (Unnecessary if m and n already coprime.)
while m % P == n % P == 0:
m, n = m // P, n // P
if n % P == 0:
hash_value = sys.hash_info.inf
else:
# Fermat's Little Theorem: pow(n, P-1, P) is 1, so
# pow(n, P-2, P) gives the inverse of n modulo P.
hash_value = (abs(m) % P) * pow(n, P - 2, P) % P
if m < 0:
hash_value = -hash_value
if hash_value == -1:
hash_value = -2
return hash_value
def hash_float(x):
"""Compute the hash of a float x."""
if math.isnan(x):
return object.__hash__(x)
elif math.isinf(x):
return sys.hash_info.inf if x > 0 else -sys.hash_info.inf
else:
return hash_fraction(*x.as_integer_ratio())
def hash_complex(z):
"""Compute the hash of a complex number z."""
hash_value = hash_float(z.real) + sys.hash_info.imag * hash_float(z.imag)
# do a signed reduction modulo 2**sys.hash_info.width
M = 2**(sys.hash_info.width - 1)
hash_value = (hash_value & (M - 1)) - (hash_value & M)
if hash_value == -1:
hash_value = -2
return hash_value
布林型別 - bool
¶
布林值表示真值。bool
型別只有兩個常量例項:True
和 False
。
如果值可以解釋為真值(參見上面的 真值測試 部分),則內建函式 bool()
會將任何值轉換為布林值。
對於邏輯運算,請使用 布林運算子 and
、or
和 not
。當將按位運算子 &
、|
、^
應用於兩個布林值時,它們會返回一個與邏輯運算“and”、“or”、“xor”等效的布林值。但是,邏輯運算子 and
、or
和 !=
應該優先於 &
、|
和 ^
。
自版本 3.12 起棄用:不推薦使用按位反轉運算子 ~
,並且在 Python 3.16 中會引發錯誤。
bool
是 int
的子類(請參見 數值型別 — int、float、complex)。在許多數值上下文中,False
和 True
的行為分別類似於整數 0 和 1。但是,不鼓勵依賴此行為;請使用 int()
顯式轉換。
迭代器型別¶
Python 支援容器的迭代概念。這是使用兩種不同的方法實現的;這些方法用於允許使用者定義的類支援迭代。下面詳細描述的序列始終支援迭代方法。
需要為一個容器物件定義一種方法,以提供 可迭代 支援。
- container.__iter__()¶
返回一個 迭代器 物件。該物件需要支援下面描述的迭代器協議。如果一個容器支援不同型別的迭代,則可以提供其他方法來專門請求這些迭代型別的迭代器。(一個支援多種迭代形式的物件的示例是樹結構,它同時支援廣度優先和深度優先遍歷。)此方法對應於 Python/C API 中 Python 物件的型別結構的
tp_iter
插槽。
迭代器物件本身需要支援以下兩種方法,它們共同構成了 迭代器協議
- iterator.__iter__()¶
返回 迭代器 物件本身。這是為了允許容器和迭代器都與
for
和in
語句一起使用。此方法對應於 Python/C API 中 Python 物件的型別結構的tp_iter
插槽。
- iterator.__next__()¶
從 迭代器 返回下一個專案。如果沒有更多專案,則引發
StopIteration
異常。此方法對應於 Python/C API 中 Python 物件的型別結構的tp_iternext
插槽。
Python 定義了多個迭代器物件,以支援對通用和特定序列型別、字典以及其他更專業的形式進行迭代。除了它們對迭代器協議的實現之外,具體的型別並不重要。
一旦迭代器的 __next__()
方法引發 StopIteration
,它必須在後續呼叫中繼續這樣做。不遵守此屬性的實現被認為是損壞的。
生成器型別¶
Python 的 生成器 提供了一種實現迭代器協議的便捷方法。如果容器物件的 __iter__()
方法是作為生成器實現的,它將自動返回一個提供 __iter__()
和 __next__()
方法的迭代器物件(從技術上講,是一個生成器物件)。有關生成器的更多資訊,請參見 yield 表示式的文件。
序列型別 — list
、tuple
、range
¶
有三種基本序列型別:列表、元組和 range 物件。專門用於處理 二進位制資料 和 文字字串 的其他序列型別將在專門的章節中介紹。
通用序列操作¶
以下表格中的操作大多數序列型別(包括可變和不可變序列)都支援。提供了 collections.abc.Sequence
ABC,以便更容易地在自定義序列型別上正確實現這些操作。
此表按優先順序升序列出了序列操作。在表中,s 和 t 是相同型別的序列,n、i、j 和 k 是整數,x 是滿足 s 施加的任何型別和值限制的任意物件。
in
和 not in
操作的優先順序與比較操作相同。+
(連線)和 *
(重複)操作的優先順序與相應的數值操作相同。[3]
運算 |
結果 |
備註 |
---|---|---|
|
如果 s 的某項等於 x,則為 |
(1) |
|
如果 s 的某項等於 x,則為 |
(1) |
|
s 和 t 的連線 |
(6)(7) |
|
等效於將 s 新增到自身 n 次 |
(2)(7) |
|
s 的第 i 項,從 0 開始 |
(3) |
|
從 i 到 j 的 s 的切片 |
(3)(4) |
|
從 i 到 j,步長為 k 的 s 的切片 |
(3)(5) |
|
s 的長度 |
|
|
s 的最小項 |
|
|
s 的最大項 |
|
|
x 在 s 中第一次出現的索引(在索引 i 或之後且在索引 j 之前) |
(8) |
|
x 在 s 中出現的總次數 |
相同型別的序列也支援比較。特別是,元組和列表透過比較對應的元素按字典順序進行比較。這意味著,要比較相等,每個元素都必須比較相等,並且兩個序列必須是相同的型別且長度相同。(有關詳細資訊,請參見語言參考中的 比較。)
可變序列的前向和反向迭代器使用索引訪問值。即使底層序列發生變異,該索引也將繼續向前(或向後)移動。迭代器僅在遇到 IndexError
或 StopIteration
時(或當索引降至零以下時)終止。
備註
雖然
in
和not in
操作通常僅用於簡單的包含測試,但某些特殊的序列(例如str
、bytes
和bytearray
)也將其用於子序列測試>>> "gg" in "eggs" True
小於
0
的 n 值被視為0
(產生與 s 相同型別的空序列)。請注意,序列 s 中的項不會被複制;它們被多次引用。這經常困擾新的 Python 程式設計師;考慮一下>>> lists = [[]] * 3 >>> lists [[], [], []] >>> lists[0].append(3) >>> lists [[3], [3], [3]]
發生的情況是
[[]]
是一個包含一個空列表的單元素列表,因此[[]] * 3
的所有三個元素都引用此單個空列表。修改lists
的任何元素都會修改這個單個列表。你可以這樣建立一個不同的列表的列表>>> lists = [[] for i in range(3)] >>> lists[0].append(3) >>> lists[1].append(5) >>> lists[2].append(7) >>> lists [[3], [5], [7]]
更多解釋請參見 FAQ 條目 如何建立多維列表?。
如果 i 或 j 為負數,則該索引相對於序列 s 的末尾:替換為
len(s) + i
或len(s) + j
。但是請注意,-0
仍然是0
。從 i 到 j 的 s 切片定義為索引為 k 的項的序列,使得
i <= k < j
。如果 i 或 j 大於len(s)
,則使用len(s)
。如果省略 i 或 i 為None
,則使用0
。如果省略 j 或 j 為None
,則使用len(s)
。如果 i 大於或等於 j,則切片為空。從 i 到 j,步長為 k 的 s 切片定義為索引為
x = i + n*k
的項的序列,使得0 <= n < (j-i)/k
。換句話說,索引為i
、i+k
、i+2*k
、i+3*k
等,直到到達 j 時停止(但不包括 j)。當 k 為正數時,如果 i 和 j 大於len(s)
,則它們會減小為len(s)
。當 k 為負數時,如果 i 和 j 大於len(s) - 1
,則它們會減小為len(s) - 1
。如果省略 i 或 j 或它們為None
,則它們會成為“末尾”值(末尾取決於 k 的符號)。請注意,k 不能為零。如果 k 為None
,則將其視為1
。連線不可變序列總是會產生一個新物件。這意味著透過重複連線來構建序列將在總序列長度中具有二次執行時成本。要獲得線性執行時成本,必須切換到以下替代方案之一
如果連線
str
物件,則可以構建一個列表,並在最後使用str.join()
,或者寫入io.StringIO
例項並在完成後檢索其值如果連線
bytes
物件,則可以類似地使用bytes.join()
或io.BytesIO
,或者可以使用bytearray
物件進行就地連線。bytearray
物件是可變的,並具有高效的整體分配機制對於其他型別,請檢視相關的類文件
某些序列型別(例如
range
)僅支援遵循特定模式的項序列,因此不支援序列連線或重複。當在 s 中找不到 x 時,
index
會引發ValueError
。並非所有實現都支援傳遞附加引數 i 和 j。這些引數允許高效地搜尋序列的子部分。傳遞額外的引數大致相當於使用s[i:j].index(x)
,只是不復制任何資料,並且返回的索引相對於序列的開頭而不是切片的開頭。
不可變序列型別¶
不可變序列型別通常實現的唯一操作(可變序列型別也未實現的操作)是對 hash()
內建函式的支援。
這種支援允許將不可變序列(例如 tuple
例項)用作 dict
鍵,並存儲在 set
和 frozenset
例項中。
嘗試雜湊包含不可雜湊值的不可變序列將導致 TypeError
。
可變序列型別¶
下表中的操作定義在可變序列型別上。提供了 collections.abc.MutableSequence
ABC,以便更容易地在自定義序列型別上正確實現這些操作。
在表中,s 是一個可變序列型別的例項,t 是任何可迭代物件,x 是一個任意物件,它滿足 s 施加的任何型別和值限制(例如,bytearray
只接受滿足值限制 0 <= x <= 255
的整數)。
運算 |
結果 |
備註 |
---|---|---|
|
s 的第 i 項被 x 替換 |
|
|
s 中從 i 到 j 的切片被可迭代物件 t 的內容替換 |
|
|
與 |
|
|
|
(1) |
|
從列表中刪除 |
|
|
將 x 追加到序列的末尾(與 |
|
|
刪除 s 中的所有項(與 |
(5) |
|
建立 s 的淺複製(與 |
(5) |
|
使用 t 的內容擴充套件 s(在大多數情況下與 |
|
|
用其內容重複 n 次來更新 s |
(6) |
|
在 i 給定的索引處將 x 插入到 s 中(與 |
|
|
檢索索引 i 處的項,並將其從 s 中刪除 |
(2) |
|
從 s 中刪除第一個 |
(3) |
|
就地反轉 s 的項 |
(4) |
備註
如果 k 不等於
1
,則 t 的長度必須與它替換的切片長度相同。可選引數 i 預設為
-1
,因此預設情況下,刪除並返回最後一項。當在 s 中未找到 x 時,
remove()
引發ValueError
。當反轉大序列時,為了節省空間,
reverse()
方法就地修改序列。為了提醒使用者它透過副作用操作,它不返回反轉後的序列。包含
clear()
和copy()
是為了與不支援切片操作的可變容器(如dict
和set
)的介面保持一致。copy()
不是collections.abc.MutableSequence
ABC 的一部分,但大多數具體的列表類都提供了它。3.3 版本新增:
clear()
和copy()
方法。值 n 是一個整數,或者是一個實現
__index__()
的物件。 n 的零值和負值會清除序列。序列中的項不會被複制;它們會被多次引用,如 通用序列操作 中s * n
所述。
列表¶
列表是可變序列,通常用於儲存同類項的集合(其中相似程度的確切程度會因應用程式而異)。
- class list([iterable])¶
列表可以透過多種方式構建
使用一對中括號表示空列表:
[]
使用中括號,用逗號分隔項:
[a]
、[a, b, c]
使用列表推導式:
[x for x in iterable]
使用型別建構函式:
list()
或list(iterable)
建構函式構建一個列表,其項與 iterable 的項相同且順序相同。iterable 可以是序列、支援迭代的容器或迭代器物件。如果 iterable 已經是一個列表,則會製作並返回一個副本,類似於
iterable[:]
。例如,list('abc')
返回['a', 'b', 'c']
,list( (1, 2, 3) )
返回[1, 2, 3]
。如果沒有給出引數,則建構函式會建立一個新的空列表[]
。許多其他操作也會生成列表,包括
sorted()
內建函式。列表實現了所有 通用 和 可變 序列操作。列表還提供了以下附加方法
- sort(*, key=None, reverse=False)¶
此方法就地對列表進行排序,僅使用項之間的
<
比較。不會抑制異常 - 如果任何比較操作失敗,整個排序操作將失敗(並且列表很可能處於部分修改狀態)。sort()
接受兩個只能透過關鍵字傳遞的引數(僅限關鍵字的引數)key 指定一個引數的函式,用於從每個列表元素中提取比較鍵(例如,
key=str.lower
)。列表中每個項對應的鍵只計算一次,然後用於整個排序過程。None
的預設值表示直接對列表項進行排序,而不計算單獨的鍵值。functools.cmp_to_key()
實用程式可用於將 2.x 風格的 cmp 函式轉換為 key 函式。reverse 是一個布林值。如果設定為
True
,則列表元素的排序方式就像每個比較都被反轉一樣。當排序大序列時,此方法就地修改序列以節省空間。為了提醒使用者它透過副作用操作,它不返回排序後的序列(使用
sorted()
顯式請求一個新的排序列表例項)。sort()
方法保證是穩定的。如果排序保證不改變比較相等的元素的相對順序,則排序是穩定的——這對於多次排序很有用(例如,按部門排序,然後按工資等級排序)。有關排序示例和簡短的排序教程,請參閱 排序技術。
CPython 實現細節: 當列表正在排序時,嘗試修改甚至檢查列表的效果是未定義的。 Python 的 C 實現使列表在持續時間內顯示為空,並且如果檢測到列表在排序期間已發生變異,則會引發
ValueError
。
元組¶
元組是不可變的序列,通常用於儲存異構資料集合(例如 enumerate()
內建函式生成的 2 元組)。元組也用於需要同構資料的不可變序列的場景(例如允許儲存在 set
或 dict
例項中)。
- class tuple([iterable])¶
元組可以透過多種方式構造:
使用一對括號表示空元組:
()
使用尾隨逗號表示單例元組:
a,
或(a,)
使用逗號分隔專案:
a, b, c
或(a, b, c)
使用
tuple()
內建函式:tuple()
或tuple(iterable)
建構函式建立一個元組,其專案與 iterable 的專案相同且順序相同。iterable 可以是序列、支援迭代的容器或迭代器物件。如果 iterable 已經是一個元組,則它將保持不變返回。例如,
tuple('abc')
返回('a', 'b', 'c')
,而tuple( [1, 2, 3] )
返回(1, 2, 3)
。如果沒有給出引數,建構函式將建立一個新的空元組()
。請注意,實際上使之成為元組的是逗號,而不是括號。括號是可選的,除非是空元組的情況,或者需要它們來避免語法歧義。例如,
f(a, b, c)
是一個帶有三個引數的函式呼叫,而f((a, b, c))
是一個以 3 元組作為唯一引數的函式呼叫。元組實現了所有通用序列操作。
對於按名稱訪問比按索引訪問更清晰的異構資料集合,collections.namedtuple()
可能比簡單的元組物件更合適的選擇。
範圍¶
range
型別表示一個不可變的數字序列,通常用於在 for
迴圈中迴圈特定次數。
- class range(stop)¶
- class range(start, stop[, step])
range 建構函式的引數必須是整數(可以是內建的
int
或任何實現了__index__()
特殊方法的物件)。如果省略 step 引數,則預設為1
。如果省略 start 引數,則預設為0
。如果 step 為零,則會引發ValueError
。對於正的 step,範圍
r
的內容由公式r[i] = start + step*i
確定,其中i >= 0
且r[i] < stop
。對於負的 step,範圍的內容仍然由公式
r[i] = start + step*i
確定,但約束條件是i >= 0
且r[i] > stop
。如果
r[0]
不滿足值約束,則範圍物件將為空。範圍支援負索引,但這些索引被解釋為從正索引確定的序列的末尾開始索引。允許包含大於
sys.maxsize
的絕對值的範圍,但某些功能(例如len()
)可能會引發OverflowError
。範圍示例
>>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(range(1, 11)) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> list(range(0, 30, 5)) [0, 5, 10, 15, 20, 25] >>> list(range(0, 10, 3)) [0, 3, 6, 9] >>> list(range(0, -10, -1)) [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] >>> list(range(0)) [] >>> list(range(1, 0)) []
範圍實現了除串聯和重複之外的所有通用序列操作(因為範圍物件只能表示遵循嚴格模式的序列,而重複和串聯通常會違反該模式)。
- start¶
start 引數的值(如果未提供該引數,則為
0
)
- stop¶
stop 引數的值
- step¶
step 引數的值(如果未提供該引數,則為
1
)
與常規的 list
或 tuple
相比,range
型別的優勢在於,range
物件始終佔用相同(少量)的記憶體,無論其表示的範圍大小如何(因為它只儲存 start
、stop
和 step
值,並根據需要計算單個專案和子範圍)。
範圍物件實現了 collections.abc.Sequence
ABC,並提供了諸如包含測試、元素索引查詢、切片和對負索引的支援等功能(請參閱 序列型別 — list、tuple、range)
>>> r = range(0, 20, 2)
>>> r
range(0, 20, 2)
>>> 11 in r
False
>>> 10 in r
True
>>> r.index(10)
5
>>> r[5]
10
>>> r[:5]
range(0, 10, 2)
>>> r[-1]
18
使用 ==
和 !=
測試範圍物件是否相等會將它們作為序列進行比較。也就是說,如果兩個範圍物件表示相同的值序列,則認為它們是相等的。(請注意,兩個比較相等的範圍物件可能具有不同的 start
、stop
和 step
屬性,例如 range(0) == range(2, 1, 3)
或 range(0, 3, 2) == range(0, 4, 2)
。)
在 3.2 版本中更改: 實現序列 ABC。支援切片和負索引。以恆定時間測試 int
物件是否為成員,而不是遍歷所有專案。
另請參閱
linspace 配方 展示瞭如何實現一個適用於浮點數應用的 range 惰性版本。
文字序列型別 — str
¶
Python 中的文字資料使用 str
物件或字串來處理。字串是 Unicode 程式碼點的不可變序列。字串字面值可以使用多種方式書寫
單引號:
'允許嵌入 "雙" 引號'
雙引號:
"允許嵌入 '單' 引號"
三引號:
'''三個 單 引號'''
,"""三個 雙 引號"""
三引號字串可以跨越多行 - 所有相關的空白符都將包含在字串字面值中。
屬於單個表示式一部分且彼此之間只有空白符的字串字面值將被隱式轉換為單個字串字面值。也就是說, ("spam " "eggs") == "spam eggs"
。
有關各種形式的字串字面值(包括支援的轉義序列)以及停用大多數轉義序列處理的 r
(“原始”) 字首的更多資訊,請參閱字串和位元組字面值。
字串也可以使用 str
建構函式從其他物件建立。
由於沒有單獨的“字元”型別,索引字串會生成長度為 1 的字串。也就是說,對於非空字串 *s*, s[0] == s[0:1]
。
也沒有可變字串型別,但是可以使用 str.join()
或 io.StringIO
從多個片段高效地構建字串。
在 3.3 版本中更改: 為了向後相容 Python 2 系列,字串字面值再次允許使用 u
字首。它對字串字面值的含義沒有影響,並且不能與 r
字首結合使用。
- class str(object='')¶
- class str(object=b'', encoding='utf-8', errors='strict')
返回 *object* 的 字串 版本。如果未提供 *object*,則返回空字串。否則,
str()
的行為取決於是否給出了 *encoding* 或 *errors*,如下所示。如果既未給出 *encoding* 也未給出 *errors*,則
str(object)
返回type(object).__str__(object)
,它是 *object* 的“非正式”或格式良好的可列印字串表示形式。對於字串物件,這是字串本身。如果 *object* 沒有__str__()
方法,則str()
將回退到返回repr(object)
。如果給出了 *encoding* 或 *errors* 中的至少一個,則 *object* 應該是一個 bytes-like object (例如
bytes
或bytearray
)。在這種情況下,如果 *object* 是一個bytes
(或bytearray
)物件,則str(bytes, encoding, errors)
等效於bytes.decode(encoding, errors)
。否則,在呼叫bytes.decode()
之前,將獲取緩衝區物件的基礎位元組物件。有關緩衝區物件的資訊,請參閱二進位制序列型別 — bytes、bytearray、memoryview 和 緩衝區協議。將
bytes
物件傳遞給沒有 *encoding* 或 *errors* 引數的str()
屬於返回非正式字串表示形式的第一種情況(另請參閱 Python 的-b
命令列選項)。例如>>> str(b'Zoot!') "b'Zoot!'"
有關
str
類及其方法的更多資訊,請參閱文字序列型別 — str 和下面的字串方法部分。要輸出格式化的字串,請參閱 f-字串 和 格式字串語法 部分。此外,請參閱文字處理服務部分。
字串方法¶
字串實現了所有通用序列操作,以及下面描述的其他方法。
字串還支援兩種字串格式化風格,一種提供了高度的靈活性和自定義功能(請參閱 str.format()
、格式字串語法 和 自定義字串格式化),另一種基於 C printf
樣式格式化,它處理的類型範圍較窄且使用起來稍微困難一些,但對於它可以處理的情況,通常速度更快 (printf 樣式的字串格式化)。
標準庫的文字處理服務部分涵蓋了許多其他模組,這些模組提供了各種與文字相關的實用程式(包括 re
模組中的正則表示式支援)。
- str.capitalize()¶
返回字串的副本,其中第一個字元大寫,其餘字元小寫。
在 3.8 版本中更改: 現在,第一個字元將轉換為首字母大寫,而不是大寫。這意味著像連字這樣的字元將只將其首字母大寫,而不是整個字元。
- str.casefold()¶
返回字串的 casefolded 副本。Casefolded 字串可用於不區分大小寫的匹配。
Casefolding 類似於小寫,但更激進,因為它旨在消除字串中的所有大小寫差異。例如,德語小寫字母
'ß'
等效於"ss"
。由於它已經是小寫,lower()
對'ß'
無效;casefold()
會將其轉換為"ss"
。大小寫摺疊演算法在Unicode 標準的第 3.13 節“預設大小寫摺疊”中描述。
3.3 版本中新增。
- str.center(width[, fillchar])¶
返回長度為 *width* 的字串中居中的字串。使用指定的 *fillchar* 進行填充(預設為 ASCII 空格)。如果 *width* 小於或等於
len(s)
,則返回原始字串。
- str.count(sub[, start[, end]])¶
返回子字串 *sub* 在範圍 [*start*, *end*] 內的非重疊出現次數。可選引數 *start* 和 *end* 的解釋方式與切片表示法中相同。
如果 sub 為空,則返回字元之間空字串的數量,該數量等於字串的長度加一。
- str.encode(encoding='utf-8', errors='strict')¶
返回以
bytes
編碼的字串。encoding 預設為
'utf-8'
;有關可能的值,請參閱 標準編碼。errors 控制如何處理編碼錯誤。 如果是
'strict'
(預設值),則會引發UnicodeError
異常。其他可能的值包括'ignore'
、'replace'
、'xmlcharrefreplace'
、'backslashreplace'
以及透過codecs.register_error()
註冊的任何其他名稱。 有關詳細資訊,請參閱 錯誤處理程式。出於效能原因,除非實際發生編碼錯誤、啟用 Python 開發模式 或使用 除錯版本,否則不會檢查 errors 值的有效性。
在 3.1 版本中更改: 增加了對關鍵字引數的支援。
在 3.9 版本中更改: 現在,在 Python 開發模式 和 除錯模式 下檢查 errors 引數的值。
- str.endswith(suffix[, start[, end]])¶
如果字串以指定的 suffix 結尾,則返回
True
,否則返回False
。suffix 也可以是要查詢的字尾元組。使用可選的 start,從該位置開始測試。使用可選的 end,在該位置停止比較。
- str.expandtabs(tabsize=8)¶
返回字串的副本,其中所有制表符都替換為一個或多個空格,具體取決於當前列和給定的製表符大小。製表符位置每隔 tabsize 個字元出現一次(預設為 8,製表符位置位於列 0、8、16 等)。要展開字串,當前列設定為零,並逐個字元地檢查字串。如果字元是製表符 (
\t
),則在結果中插入一個或多個空格字元,直到當前列等於下一個製表符位置。(製表符本身不復制。)如果字元是換行符 (\n
) 或回車符 (\r
),則複製該字元,並將當前列重置為零。任何其他字元都保持不變地複製,並且當前列遞增 1,而與列印時字元的表示方式無關。>>> '01\t012\t0123\t01234'.expandtabs() '01 012 0123 01234' >>> '01\t012\t0123\t01234'.expandtabs(4) '01 012 0123 01234'
- str.find(sub[, start[, end]])¶
返回字串中子字串 sub 在切片
s[start:end]
中找到的最低索引。可選引數 start 和 end 的解釋方式與切片表示法相同。如果未找到 sub,則返回-1
。
- str.format(*args, **kwargs)¶
執行字串格式化操作。呼叫此方法的字串可以包含由大括號
{}
分隔的文字或替換欄位。每個替換欄位都包含位置引數的數字索引,或關鍵字引數的名稱。返回字串的副本,其中每個替換欄位都替換為相應引數的字串值。>>> "The sum of 1 + 2 is {0}".format(1+2) 'The sum of 1 + 2 is 3'
有關可以在格式字串中指定的各種格式化選項的說明,請參閱 格式字串語法。
注意
當使用
n
型別(例如:'{:n}'.format(1234)
)格式化數字(int
、float
、complex
、decimal.Decimal
和子類)時,如果localeconv()
的decimal_point
和thousands_sep
欄位是非 ASCII 或長度超過 1 個位元組,並且LC_NUMERIC
區域設定與LC_CTYPE
區域設定不同,則該函式會將LC_CTYPE
區域設定臨時設定為LC_NUMERIC
區域設定以解碼它們。此臨時更改會影響其他執行緒。在 3.7 版本中更改: 當使用
n
型別格式化數字時,該函式會在某些情況下臨時將LC_CTYPE
區域設定設定為LC_NUMERIC
區域設定。
- str.format_map(mapping, /)¶
類似於
str.format(**mapping)
,不同之處在於直接使用mapping
,而不將其複製到dict
。如果例如mapping
是 dict 子類,則此操作很有用。>>> class Default(dict): ... def __missing__(self, key): ... return key ... >>> '{name} was born in {country}'.format_map(Default(name='Guido')) 'Guido was born in country'
3.2 版本新增。
- str.index(sub[, start[, end]])¶
與
find()
類似,但當找不到子字串時,會引發ValueError
。
- str.isalnum()¶
如果字串中的所有字元都是字母數字並且至少有一個字元,則返回
True
,否則返回False
。如果以下之一返回True
,則字元c
為字母數字:c.isalpha()
、c.isdecimal()
、c.isdigit()
或c.isnumeric()
。
- str.isalpha()¶
如果字串中的所有字元都是字母,並且至少有一個字元,則返回
True
,否則返回False
。字母字元是在 Unicode 字元資料庫中定義為“字母”的字元,即通用類別屬性為“Lm”、“Lt”、“Lu”、“Ll”或“Lo”的字元。請注意,這與 Unicode 標準的第 4.10 節“字母、文字和表意文字”中定義的字母屬性不同。
- str.isascii()¶
如果字串為空或字串中的所有字元都是 ASCII 字元,則返回
True
,否則返回False
。ASCII 字元的程式碼點範圍為 U+0000-U+007F。在 3.7 版本中新增。
- str.isdecimal()¶
如果字串中的所有字元都是十進位制字元,並且至少有一個字元,則返回
True
,否則返回False
。十進位制字元是那些可以用來形成十進位制數字的字元,例如 U+0660,阿拉伯-印度數字零。形式上,十進位制字元是 Unicode 通用類別“Nd”中的字元。
- str.isdigit()¶
如果字串中的所有字元都是數字,並且至少有一個字元,則返回
True
,否則返回False
。數字包括十進位制字元和需要特殊處理的數字,例如相容的上標數字。這涵蓋了無法用於形成十進位制數字的數字,例如佉盧文數字。形式上,數字是具有屬性值 Numeric_Type=Digit 或 Numeric_Type=Decimal 的字元。
- str.isidentifier()¶
如果該字串根據語言定義是有效的識別符號,請參閱識別符號和關鍵字部分,則返回
True
。keyword.iskeyword()
可以用來測試字串s
是否是保留的識別符號,例如def
和class
。示例
>>> from keyword import iskeyword >>> 'hello'.isidentifier(), iskeyword('hello') (True, False) >>> 'def'.isidentifier(), iskeyword('def') (True, True)
- str.isnumeric()¶
如果字串中的所有字元都是數值字元,並且至少有一個字元,則返回
True
,否則返回False
。數值字元包括數字字元和所有具有 Unicode 數值屬性的字元,例如 U+2155,五分之一。形式上,數值字元是具有屬性值 Numeric_Type=Digit、Numeric_Type=Decimal 或 Numeric_Type=Numeric 的字元。
- str.isprintable()¶
如果字串中的所有字元都是可列印的,或者字串為空,則返回
True
,否則返回False
。不可列印的字元是在 Unicode 字元資料庫中定義為“其他”或“分隔符”的字元,但 ASCII 空格 (0x20) 除外,它被認為是可列印的。(請注意,此上下文中的可列印字元是指在對字串呼叫repr()
時不應轉義的字元。這與寫入sys.stdout
或sys.stderr
的字串的處理無關。)
- str.isspace()¶
如果字串中只有空白字元,並且至少有一個字元,則返回
True
,否則返回False
。如果一個字元在 Unicode 字元資料庫中(請參閱
unicodedata
),其通用類別為Zs
(“分隔符,空格”),或者其雙向類為WS
、B
或S
,則該字元是空白字元。
- str.istitle()¶
如果該字串是首字母大寫的字串,並且至少有一個字元,則返回
True
,例如,大寫字元只能跟在未帶大小寫的字元之後,而小寫字元只能跟在帶大小寫的字元之後。否則返回False
。
- str.isupper()¶
如果字串中所有帶大小寫的字元[4] 都是大寫,並且至少有一個帶大小寫的字元,則返回
True
,否則返回False
。>>> 'BANANA'.isupper() True >>> 'banana'.isupper() False >>> 'baNana'.isupper() False >>> ' '.isupper() False
- str.join(iterable)¶
返回一個字串,它是 iterable 中字串的串聯。如果 iterable 中有任何非字串值,包括
bytes
物件,則會引發TypeError
。元素之間的分隔符是提供此方法的字串。
- str.ljust(width[, fillchar])¶
返回在長度為 width 的字串中左對齊的字串。填充使用指定的 fillchar 完成(預設為 ASCII 空格)。如果 width 小於或等於
len(s)
,則返回原始字串。
- str.lower()¶
返回字串的副本,其中所有帶大小寫的字元[4] 都轉換為小寫。
所使用的小寫演算法在 Unicode 標準的第 3.13 節“預設大小寫摺疊”中描述。
- str.lstrip([chars])¶
返回刪除前導字元的字串的副本。chars 引數是一個字串,用於指定要刪除的字元集。如果省略或為
None
,則 chars 引數預設為刪除空白字元。chars 引數不是字首;而是剝離其值的所有組合。>>> ' spacious '.lstrip() 'spacious ' >>> 'www.example.com'.lstrip('cmowz.') 'example.com'
有關將刪除單個字首字串而不是一組字元的方法,請參閱
str.removeprefix()
。例如>>> 'Arthur: three!'.lstrip('Arthur: ') 'ee!' >>> 'Arthur: three!'.removeprefix('Arthur: ') 'three!'
- static str.maketrans(x[, y[, z]])¶
這個靜態方法返回一個可用於
str.translate()
的轉換表。如果只有一個引數,它必須是一個字典,將 Unicode 序號(整數)或字元(長度為 1 的字串)對映到 Unicode 序號、字串(任意長度)或
None
。字元鍵隨後會被轉換為序號。如果有兩個引數,它們必須是長度相等的字串,並且在生成的字典中,x 中的每個字元都會被對映到 y 中相同位置的字元。 如果有第三個引數,它必須是一個字串,其字元將在結果中被對映到
None
。
- str.partition(sep)¶
在 sep 的第一次出現處分割字串,並返回一個 3 元組,其中包含分隔符之前的部分、分隔符本身和分隔符之後的部分。如果未找到分隔符,則返回一個包含字串本身、後跟兩個空字串的 3 元組。
- str.removeprefix(prefix, /)¶
如果字串以 prefix 字串開頭,則返回
string[len(prefix):]
。否則,返回原始字串的副本。>>> 'TestHook'.removeprefix('Test') 'Hook' >>> 'BaseTestCase'.removeprefix('Test') 'BaseTestCase'
3.9 版本新增。
- str.removesuffix(suffix, /)¶
如果字串以 suffix 字串結尾並且該 suffix 不為空,則返回
string[:-len(suffix)]
。否則,返回原始字串的副本。>>> 'MiscTests'.removesuffix('Tests') 'Misc' >>> 'TmpDirMixin'.removesuffix('Tests') 'TmpDirMixin'
3.9 版本新增。
- str.replace(old, new, count=-1)¶
返回一個字串的副本,其中所有出現的子字串 old 都被替換為 new。 如果給出了 count,則只替換前 count 次出現。 如果未指定 count 或
-1
,則替換所有出現。在 3.13 版本中更改: 現在支援將 count 作為關鍵字引數。
- str.rfind(sub[, start[, end]])¶
返回字串中子字串 sub 出現的最高索引,前提是 sub 包含在
s[start:end]
中。 可選引數 start 和 end 的解釋與切片表示法相同。 如果失敗,則返回-1
。
- str.rindex(sub[, start[, end]])¶
與
rfind()
類似,但當找不到子字串 sub 時會引發ValueError
。
- str.rjust(width[, fillchar])¶
返回在長度為 width 的字串中右對齊的字串。 填充使用指定的 fillchar (預設為 ASCII 空格)完成。 如果 width 小於或等於
len(s)
,則返回原始字串。
- str.rpartition(sep)¶
在 sep 的最後一次出現處分割字串,並返回一個 3 元組,其中包含分隔符之前的部分、分隔符本身和分隔符之後的部分。 如果未找到分隔符,則返回一個 3 元組,其中包含兩個空字串,後跟字串本身。
- str.rsplit(sep=None, maxsplit=-1)¶
返回字串中的單詞列表,使用 sep 作為分隔符字串。 如果給出了 maxsplit,則最多完成 maxsplit 次分割,即 *最右側* 的分割。 如果未指定 sep 或為
None
,則任何空白字串都是分隔符。 除了從右側分割外,rsplit()
的行為類似於split()
,其詳細描述如下。
- str.rstrip([chars])¶
返回一個刪除了尾隨字元的字串副本。 chars 引數是一個字串,指定要刪除的字元集。 如果省略或為
None
,則 chars 引數預設刪除空格。 chars 引數不是字尾;而是剝離其所有值的組合。>>> ' spacious '.rstrip() ' spacious' >>> 'mississippi'.rstrip('ipz') 'mississ'
有關將刪除單個字尾字串而不是一組字元的方法,請參見
str.removesuffix()
。 例如>>> 'Monty Python'.rstrip(' Python') 'M' >>> 'Monty Python'.removesuffix(' Python') 'Monty'
- str.split(sep=None, maxsplit=-1)¶
返回字串中的單詞列表,使用 sep 作為分隔符字串。 如果給出了 maxsplit,則最多完成 maxsplit 次分割(因此,列表最多將有
maxsplit+1
個元素)。 如果未指定 maxsplit 或為-1
,則分割次數沒有限制(進行所有可能的分割)。如果給出了 sep,則連續的分隔符不會組合在一起,並且被視為分隔空字串(例如,
'1,,2'.split(',')
返回['1', '', '2']
)。 sep 引數可以由多個字元組成,作為單個分隔符(要使用多個分隔符進行分割,請使用re.split()
)。 使用指定的分隔符分割空字串將返回['']
。例如
>>> '1,2,3'.split(',') ['1', '2', '3'] >>> '1,2,3'.split(',', maxsplit=1) ['1', '2,3'] >>> '1,2,,3,'.split(',') ['1', '2', '', '3', ''] >>> '1<>2<>3<4'.split('<>') ['1', '2', '3<4']
如果未指定 sep 或為
None
,則應用不同的分割演算法:連續空白符的執行被視為單個分隔符,並且如果字串具有前導或尾隨空白符,則結果將不包含開頭或結尾的空字串。 因此,使用None
分隔符分割空字串或僅由空白符組成的字串將返回[]
。例如
>>> '1 2 3'.split() ['1', '2', '3'] >>> '1 2 3'.split(maxsplit=1) ['1', '2 3'] >>> ' 1 2 3 '.split() ['1', '2', '3']
- str.splitlines(keepends=False)¶
返回字串中的行列表,在行邊界處斷開。 除非給出了 keepends 且為 true,否則行分隔符不包含在結果列表中。
此方法會在以下行邊界處進行分割。 特別地,這些邊界是 通用換行符 的超集。
表示
描述
\n
換行
\r
回車
\r\n
回車 + 換行
\v
或\x0b
行製表符
\f
或\x0c
換頁
\x1c
檔案分隔符
\x1d
組分隔符
\x1e
記錄分隔符
\x85
下一行(C1 控制程式碼)
\u2028
行分隔符
\u2029
段落分隔符
在 3.2 版本中更改:
\v
和\f
被新增到行邊界列表中。例如
>>> 'ab c\n\nde fg\rkl\r\n'.splitlines() ['ab c', '', 'de fg', 'kl'] >>> 'ab c\n\nde fg\rkl\r\n'.splitlines(keepends=True) ['ab c\n', '\n', 'de fg\r', 'kl\r\n']
與使用分隔符字串 sep 的
split()
不同,此方法對於空字串返回空列表,並且末尾的換行符不會導致額外的行。>>> "".splitlines() [] >>> "One line\n".splitlines() ['One line']
作為比較,
split('\n')
返回>>> ''.split('\n') [''] >>> 'Two lines\n'.split('\n') ['Two lines', '']
- str.startswith(prefix[, start[, end]])¶
如果字串以 prefix 開頭,則返回
True
,否則返回False
。prefix 也可以是要查詢的字首的元組。使用可選的 start,從該位置開始測試字串。使用可選的 end,在該位置停止比較字串。
- str.strip([chars])¶
返回刪除前導和尾隨字元的字串的副本。chars 引數是一個字串,指定要刪除的字元集。如果省略或為
None
,則 chars 引數預設為刪除空格。chars 引數不是字首或字尾;而是其所有值的組合都被刪除。>>> ' spacious '.strip() 'spacious' >>> 'www.example.com'.strip('cmowz.') 'example'
最外層的前導和尾隨 chars 引數值將從字串中刪除。從前導端刪除字元,直到到達不包含在 chars 中的字元集中的字串字元。在尾隨端執行類似的操作。例如
>>> comment_string = '#....... Section 3.2.1 Issue #32 .......' >>> comment_string.strip('.#! ') 'Section 3.2.1 Issue #32'
- str.swapcase()¶
返回字串的副本,其中大寫字元轉換為小寫字元,反之亦然。請注意,
s.swapcase().swapcase() == s
不一定是真的。
- str.title()¶
返回字串的標題版本,其中單詞以大寫字元開頭,其餘字元為小寫。
例如
>>> 'Hello world'.title() 'Hello World'
該演算法使用單詞的簡單、與語言無關的定義,即連續字母的組。該定義在許多情況下都適用,但這意味著收縮和所有格中的撇號會形成單詞邊界,這可能不是想要的結果。
>>> "they're bill's friends from the UK".title() "They'Re Bill'S Friends From The Uk"
string.capwords()
函式沒有這個問題,因為它只在空格上分割單詞。或者,可以使用正則表示式構造撇號的解決方法
>>> import re >>> def titlecase(s): ... return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", ... lambda mo: mo.group(0).capitalize(), ... s) ... >>> titlecase("they're bill's friends.") "They're Bill's Friends."
- str.translate(table)¶
返回字串的副本,其中每個字元都已透過給定的轉換表對映。該表必須是一個透過
__getitem__()
實現索引的物件,通常是 對映 或 序列。當使用 Unicode 序號(整數)進行索引時,表物件可以執行以下任何操作:返回 Unicode 序號或字串,以將字元對映到一個或多個其他字元;返回None
,以從返回的字串中刪除字元;或引發LookupError
異常,以將字元對映到其自身。你可以使用
str.maketrans()
從不同格式的字元到字元的對映建立轉換對映。另請參閱
codecs
模組,以獲得更靈活的自定義字元對映方法。
- str.upper()¶
返回字串的副本,其中所有帶大小寫的字元 [4] 都轉換為大寫。請注意,如果
s
包含不帶大小寫的字元,或者如果結果字元的 Unicode 類別不是“Lu”(字母,大寫),而是例如“Lt”(字母,標題),則s.upper().isupper()
可能是False
。使用的大寫演算法在 Unicode 標準的 3.13 節“預設大小寫摺疊”中進行了描述。
- str.zfill(width)¶
返回一個字串的副本,該字串的左側填充了 ASCII
'0'
數字,以生成長度為 width 的字串。前導符號字首('+'
/'-'
)的處理方式是在符號字元之後而不是之前插入填充。如果 width 小於或等於len(s)
,則返回原始字串。例如
>>> "42".zfill(5) '00042' >>> "-42".zfill(5) '-0042'
printf
樣式字串格式化¶
注意
此處描述的格式化操作顯示了各種怪癖,這些怪癖會導致許多常見錯誤(例如,未能正確顯示元組和字典)。使用較新的 格式化字串字面量,str.format()
介面或 模板字串 可以幫助避免這些錯誤。這些替代方案中的每一個都提供了它們自己的簡單性、靈活性和/或可擴充套件性的權衡和好處。
字串物件有一個唯一的內建操作:%
運算子(取模)。這也稱為字串格式化或插值運算子。給定 format % values
(其中 format 是一個字串),format 中的 %
轉換規範將替換為 values 的零個或多個元素。效果類似於在 C 語言中使用 sprintf()
函式。例如
>>> print('%s has %d quote types.' % ('Python', 2))
Python has 2 quote types.
如果 format 需要單個引數,則 values 可以是單個非元組物件。[5] 否則,values 必須是具有格式字串指定的專案數的元組,或者是一個對映物件(例如,字典)。
轉換說明符包含兩個或多個字元,並具有以下組成部分,這些組成部分必須按此順序出現:
字元
'%'
,它標記說明符的開始。對映鍵(可選),由帶括號的字元序列組成(例如,
(somename)
)。轉換標誌(可選),它會影響某些轉換型別的結果。
最小欄位寬度(可選)。如果指定為
'*'
(星號),則實際寬度從 values 中的元組的下一個元素讀取,並且要轉換的物件位於最小欄位寬度和可選精度之後。精度(可選),以
'.'
(點)後跟精度給出。如果指定為'*'
(星號),則實際精度從 values 中的元組的下一個元素讀取,並且要轉換的值位於精度之後。長度修飾符(可選)。
轉換型別。
當右側引數是字典(或其他對映型別)時,字串中的格式必須包括一個帶括號的對映鍵,該鍵緊跟在 '%'
字元之後插入到該字典中。對映鍵從對映中選擇要格式化的值。例如
>>> print('%(language)s has %(number)03d quote types.' %
... {'language': "Python", "number": 2})
Python has 002 quote types.
在這種情況下,格式中可能不會出現 *
說明符(因為它們需要順序引數列表)。
轉換標誌字元是:
標誌 |
含義 |
---|---|
|
值轉換將使用“替代形式”(如下定義)。 |
|
數值將使用零填充進行轉換。 |
|
轉換後的值將左對齊(如果同時給定,則覆蓋 |
|
(空格)在有符號轉換產生的正數(或空字串)之前應保留一個空格。 |
|
符號字元( |
長度修飾符(h
、l
或 L
)可能存在,但會被忽略,因為它對於 Python 來說不是必需的 —— 因此例如 %ld
與 %d
相同。
轉換型別如下:
轉換 |
含義 |
備註 |
---|---|---|
|
有符號整數十進位制。 |
|
|
有符號整數十進位制。 |
|
|
有符號八進位制值。 |
(1) |
|
已過時的型別 – 它與 |
(6) |
|
有符號十六進位制(小寫)。 |
(2) |
|
有符號十六進位制(大寫)。 |
(2) |
|
浮點指數格式(小寫)。 |
(3) |
|
浮點指數格式(大寫)。 |
(3) |
|
浮點十進位制格式。 |
(3) |
|
浮點十進位制格式。 |
(3) |
|
浮點格式。如果指數小於 -4 或不小於精度,則使用小寫指數格式,否則使用十進位制格式。 |
(4) |
|
浮點格式。如果指數小於 -4 或不小於精度,則使用大寫指數格式,否則使用十進位制格式。 |
(4) |
|
單個字元(接受整數或單字元字串)。 |
|
|
字串(使用 |
(5) |
|
字串(使用 |
(5) |
|
字串(使用 |
(5) |
|
不轉換任何引數,結果為結果中的 |
備註
替代形式會在第一個數字之前插入一個前導八進位制說明符(
'0o'
)。替代形式會在第一個數字之前插入一個前導
'0x'
或'0X'
(取決於使用'x'
還是'X'
格式)。替代形式會使結果始終包含小數點,即使後面沒有數字。
精度決定小數點後的位數,預設為 6。
替代形式會使結果始終包含小數點,並且不會像其他情況一樣刪除尾隨零。
精度決定小數點前後有效數字的位數,預設為 6。
如果精度為
N
,則輸出將截斷為N
個字元。請參閱PEP 237。
由於 Python 字串具有顯式長度,因此 %s
轉換不會假定 '\0'
是字串的結尾。
在 3.1 版本中更改: 絕對值超過 1e50 的數字的 %f
轉換不再被 %g
轉換替換。
二進位制序列型別 — bytes
、 bytearray
、 memoryview
¶
用於操作二進位制資料的核心內建型別是 bytes
和 bytearray
。它們由 memoryview
支援,後者使用緩衝區協議來訪問其他二進位制物件的記憶體,而無需進行復制。
array
模組支援高效儲存基本資料型別,如 32 位整數和 IEEE754 雙精度浮點值。
位元組物件¶
位元組物件是單位元組的不可變序列。由於許多主要的二進位制協議都基於 ASCII 文字編碼,因此位元組物件提供了幾種僅在處理 ASCII 相容資料時才有效的方法,並且在許多其他方面與字串物件密切相關。
- class bytes([source[, encoding[, errors]]])¶
首先,位元組字面量的語法與字串字面量的語法大致相同,只不過添加了
b
字首單引號:
b'仍然允許嵌入"雙引號"'
雙引號:
b"仍然允許嵌入'單引號'"
三引號:
b'''3 個單引號'''
,b"""3 個雙引號"""
位元組字面量中僅允許 ASCII 字元(無論宣告的原始碼編碼如何)。任何超過 127 的二進位制值都必須使用適當的轉義序列輸入到位元組字面量中。
與字串字面量一樣,位元組字面量也可以使用
r
字首來停用轉義序列的處理。有關各種形式的位元組字面量(包括支援的轉義序列)的更多資訊,請參閱 字串和位元組字面量。雖然位元組字面量和表示形式基於 ASCII 文字,但位元組物件的行為實際上類似於整數的不可變序列,序列中的每個值都受到限制,使得
0 <= x < 256
(嘗試違反此限制將觸發ValueError
)。這樣做是為了強調,雖然許多二進位制格式包含基於 ASCII 的元素,並且可以使用一些面向文字的演算法進行有用的操作,但這對於任意二進位制資料來說通常不是這種情況(盲目地將文字處理演算法應用於與 ASCII 不相容的二進位制資料格式通常會導致資料損壞)。除了字面形式之外,還可以透過多種其他方式建立位元組物件
指定長度的零填充位元組物件:
bytes(10)
從整數的可迭代物件中:
bytes(range(20))
透過緩衝區協議複製現有二進位制資料:
bytes(obj)
另請參閱 bytes 內建函式。
由於 2 個十六進位制數字恰好對應一個位元組,因此十六進位制數字是描述二進位制資料的常用格式。因此,位元組型別有一個額外的類方法來讀取該格式的資料
- classmethod fromhex(string)¶
這個
bytes
類方法返回一個位元組物件,解碼給定的字串物件。該字串必須包含每個位元組兩個十六進位制數字,並忽略 ASCII 空白。>>> bytes.fromhex('2Ef0 F1f2 ') b'.\xf0\xf1\xf2'
在 3.7 版本中更改:
bytes.fromhex()
現在跳過字串中的所有 ASCII 空白,而不僅僅是空格。
存在反向轉換函式,可以將位元組物件轉換為其十六進位制表示形式。
- hex([sep[, bytes_per_sep]])¶
返回一個字串物件,其中包含例項中每個位元組的兩個十六進位制數字。
>>> b'\xf0\xf1\xf2'.hex() 'f0f1f2'
如果你想讓十六進位制字串更易於閱讀,你可以指定一個單字元分隔符 sep 引數,將其包含在輸出中。預設情況下,此分隔符將包含在每個位元組之間。第二個可選的 bytes_per_sep 引數控制間距。正值從右側計算分隔符位置,負值從左側計算。
>>> value = b'\xf0\xf1\xf2' >>> value.hex('-') 'f0-f1-f2' >>> value.hex('_', 2) 'f0_f1f2' >>> b'UUDDLRLRAB'.hex(' ', -4) '55554444 4c524c52 4142'
在 3.5 版本中新增。
在 3.8 版本中更改:
bytes.hex()
現在支援可選的 sep 和 bytes_per_sep 引數,以在十六進位制輸出中的位元組之間插入分隔符。
由於 bytes 物件是整數序列(類似於元組),對於 bytes 物件 b,b[0]
將是一個整數,而 b[0:1]
將是一個長度為 1 的 bytes 物件。(這與文字字串形成對比,在文字字串中,索引和切片都將產生長度為 1 的字串)
bytes 物件的表示形式使用字面量格式(b'...'
),因為它通常比例如 bytes([46, 46, 46])
更實用。 你始終可以使用 list(b)
將 bytes 物件轉換為整數列表。
Bytearray 物件¶
- class bytearray([source[, encoding[, errors]]])¶
bytearray 物件沒有專門的字面量語法,它們始終透過呼叫建構函式來建立
建立空例項:
bytearray()
建立具有給定長度的零填充例項:
bytearray(10)
從整數的可迭代物件建立:
bytearray(range(20))
透過緩衝區協議複製現有二進位制資料:
bytearray(b'Hi!')
由於 bytearray 物件是可變的,它們除了 Bytes 和 Bytearray 操作 中描述的常見 bytes 和 bytearray 操作之外,還支援 可變 序列操作。
另請參閱 bytearray 內建函式。
由於 2 位十六進位制數字恰好對應一個位元組,十六進位制數字是描述二進位制資料常用的格式。因此,bytearray 型別有一個額外的類方法來讀取該格式的資料
- classmethod fromhex(string)¶
這個
bytearray
類方法返回 bytearray 物件,解碼給定的字串物件。該字串必須包含每個位元組的兩位十六進位制數字,並忽略 ASCII 空白符。>>> bytearray.fromhex('2Ef0 F1f2 ') bytearray(b'.\xf0\xf1\xf2')
在 3.7 版本中更改:
bytearray.fromhex()
現在跳過字串中的所有 ASCII 空白符,而不僅僅是空格。
存在一個反向轉換函式,用於將 bytearray 物件轉換為其十六進位制表示形式。
- hex([sep[, bytes_per_sep]])¶
返回一個字串物件,其中包含例項中每個位元組的兩個十六進位制數字。
>>> bytearray(b'\xf0\xf1\xf2').hex() 'f0f1f2'
在 3.5 版本中新增。
在 3.8 版本中更改: 類似於
bytes.hex()
,bytearray.hex()
現在支援可選的 sep 和 bytes_per_sep 引數,以在十六進位制輸出中的位元組之間插入分隔符。
由於 bytearray 物件是整數序列(類似於列表),對於 bytearray 物件 b,b[0]
將是一個整數,而 b[0:1]
將是一個長度為 1 的 bytearray 物件。(這與文字字串形成對比,在文字字串中,索引和切片都將產生長度為 1 的字串)
bytearray 物件的表示形式使用 bytes 字面量格式(bytearray(b'...')
),因為它通常比例如 bytearray([46, 46, 46])
更實用。你始終可以使用 list(b)
將 bytearray 物件轉換為整數列表。
Bytes 和 Bytearray 操作¶
bytes 和 bytearray 物件都支援常見的 序列操作。它們不僅與相同型別的運算元相互操作,而且還與任何 類位元組物件 相互操作。由於這種靈活性,它們可以在操作中自由混合而不會導致錯誤。但是,結果的返回型別可能取決於運算元的順序。
注意
bytes 和 bytearray 物件的方法不接受字串作為它們的引數,就像字串的方法不接受 bytes 作為它們的引數一樣。例如,你必須編寫
a = "abc"
b = a.replace("a", "f")
和
a = b"abc"
b = a.replace(b"a", b"f")
一些 bytes 和 bytearray 操作假定使用 ASCII 相容的二進位制格式,因此在處理任意二進位制資料時應避免使用。這些限制將在下面介紹。
注意
使用這些基於 ASCII 的操作來操作未以 ASCII 格式儲存的二進位制資料可能會導致資料損壞。
以下 bytes 和 bytearray 物件的方法可以與任意二進位制資料一起使用。
- bytes.count(sub[, start[, end]])¶
- bytearray.count(sub[, start[, end]])¶
返回在 [start, end] 範圍內子序列 sub 的非重疊出現次數。可選引數 start 和 end 的解釋方式與切片表示法相同。
要搜尋的子序列可以是任何 類位元組物件 或 0 到 255 範圍內的整數。
如果 sub 為空,則返回字元之間空切片的數量,該數量是位元組物件的長度加一。
在 3.3 版本中更改: 也接受 0 到 255 範圍內的整數作為子序列。
- bytes.removeprefix(prefix, /)¶
- bytearray.removeprefix(prefix, /)¶
如果二進位制資料以 prefix 字串開頭,則返回
bytes[len(prefix):]
。否則,返回原始二進位制資料的副本>>> b'TestHook'.removeprefix(b'Test') b'Hook' >>> b'BaseTestCase'.removeprefix(b'Test') b'BaseTestCase'
prefix 可以是任何 類位元組物件。
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
3.9 版本新增。
- bytes.removesuffix(suffix, /)¶
- bytearray.removesuffix(suffix, /)¶
如果二進位制資料以 suffix 字串結尾,並且該 suffix 不為空,則返回
bytes[:-len(suffix)]
。否則,返回原始二進位制資料的副本>>> b'MiscTests'.removesuffix(b'Tests') b'Misc' >>> b'TmpDirMixin'.removesuffix(b'Tests') b'TmpDirMixin'
suffix 可以是任何 類位元組物件。
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
3.9 版本新增。
- bytes.decode(encoding='utf-8', errors='strict')¶
- bytearray.decode(encoding='utf-8', errors='strict')¶
返回解碼為
str
的位元組。encoding 預設為
'utf-8'
;有關可能的值,請參閱 標準編碼。errors 控制如何處理解碼錯誤。如果為
'strict'
(預設值),則會引發UnicodeError
異常。其他可能的值為'ignore'
、'replace'
以及透過codecs.register_error()
註冊的任何其他名稱。有關詳細資訊,請參閱 錯誤處理程式。出於效能考慮,除非實際發生解碼錯誤,否則不會檢查 errors 的值的有效性,或者啟用了 Python 開發模式,或者使用了 除錯構建。
注意
將 encoding 引數傳遞給
str
允許直接解碼任何 bytes-like 物件,而無需建立臨時的bytes
或bytearray
物件。在 3.1 版本中更改: 增加了對關鍵字引數的支援。
在 3.9 版本中更改: 現在,在 Python 開發模式 和 除錯模式 下檢查 errors 引數的值。
- bytes.endswith(suffix[, start[, end]])¶
- bytearray.endswith(suffix[, start[, end]])¶
如果二進位制資料以指定的 suffix 結尾,則返回
True
,否則返回False
。suffix 也可以是要查詢的字尾的元組。使用可選的 start,從該位置開始測試。使用可選的 end,在該位置停止比較。要搜尋的字尾可以是任何 bytes-like 物件。
- bytes.find(sub[, start[, end]])¶
- bytearray.find(sub[, start[, end]])¶
返回資料中找到子序列 sub 的最低索引,使得 sub 包含在切片
s[start:end]
中。可選引數 start 和 end 的解釋方式與切片表示法相同。如果未找到 sub,則返回-1
。要搜尋的子序列可以是任何 類位元組物件 或 0 到 255 範圍內的整數。
在 3.3 版本中更改: 也接受 0 到 255 範圍內的整數作為子序列。
- bytes.index(sub[, start[, end]])¶
- bytearray.index(sub[, start[, end]])¶
與
find()
類似,但當未找到子序列時會引發ValueError
。要搜尋的子序列可以是任何 類位元組物件 或 0 到 255 範圍內的整數。
在 3.3 版本中更改: 也接受 0 到 255 範圍內的整數作為子序列。
- bytes.join(iterable)¶
- bytearray.join(iterable)¶
返回一個位元組或位元組陣列物件,它是 iterable 中二進位制資料序列的連線。如果 iterable 中有任何值不是 bytes-like 物件,包括
str
物件,則會引發TypeError
。元素之間的分隔符是提供此方法的位元組或位元組陣列物件的內容。
- static bytes.maketrans(from, to)¶
- static bytearray.maketrans(from, to)¶
此靜態方法返回一個可用於
bytes.translate()
的轉換表,該表會將 from 中的每個字元對映到 to 中相同位置的字元;from 和 to 都必須是 bytes-like 物件 且具有相同的長度。在 3.1 版本中新增。
- bytes.partition(sep)¶
- bytearray.partition(sep)¶
在第一次出現 sep 時拆分序列,並返回一個包含分隔符之前的部分、分隔符本身或其位元組陣列副本以及分隔符之後的部分的 3 元組。如果未找到分隔符,則返回一個包含原始序列副本、後跟兩個空位元組或位元組陣列物件的 3 元組。
要搜尋的分隔符可以是任何 bytes-like 物件。
- bytes.replace(old, new[, count])¶
- bytearray.replace(old, new[, count])¶
返回序列的副本,其中子序列 old 的所有出現都被 new 替換。如果給出了可選引數 count,則僅替換前 count 次出現。
要搜尋的子序列及其替換可以是任何 bytes-like 物件。
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
- bytes.rfind(sub[, start[, end]])¶
- bytearray.rfind(sub[, start[, end]])¶
返回序列中找到子序列 sub 的最高索引,使得 sub 包含在
s[start:end]
中。可選引數 start 和 end 的解釋方式與切片表示法相同。失敗時返回-1
。要搜尋的子序列可以是任何 類位元組物件 或 0 到 255 範圍內的整數。
在 3.3 版本中更改: 也接受 0 到 255 範圍內的整數作為子序列。
- bytes.rindex(sub[, start[, end]])¶
- bytearray.rindex(sub[, start[, end]])¶
與
rfind()
類似,但當未找到子序列 sub 時會引發ValueError
異常。要搜尋的子序列可以是任何 類位元組物件 或 0 到 255 範圍內的整數。
在 3.3 版本中更改: 也接受 0 到 255 範圍內的整數作為子序列。
- bytes.rpartition(sep)¶
- bytearray.rpartition(sep)¶
在最後一次出現 sep 的位置分割序列,並返回一個 3 元組,其中包含分隔符之前的部分、分隔符本身或其 bytearray 副本以及分隔符之後的部分。如果未找到分隔符,則返回一個 3 元組,其中包含兩個空的 bytes 或 bytearray 物件,後跟原始序列的副本。
要搜尋的分隔符可以是任何 bytes-like 物件。
- bytes.startswith(prefix[, start[, end]])¶
- bytearray.startswith(prefix[, start[, end]])¶
如果二進位制資料以指定的 prefix 開頭,則返回
True
,否則返回False
。prefix 也可以是要查詢的字首的元組。使用可選的 start,從該位置開始測試。使用可選的 end,在該位置停止比較。要搜尋的字首可以是任何 bytes-like object。
- bytes.translate(table, /, delete=b'')¶
- bytearray.translate(table, /, delete=b'')¶
返回 bytes 或 bytearray 物件的副本,其中可選引數 delete 中出現的所有位元組都會被刪除,並且剩餘的位元組已透過給定的轉換表進行對映,該表必須是長度為 256 的 bytes 物件。
您可以使用
bytes.maketrans()
方法建立轉換表。對於僅刪除字元的轉換,請將 table 引數設定為
None
>>> b'read this short text'.translate(None, b'aeiou') b'rd ths shrt txt'
在 3.6 版本中更改: 現在支援將 delete 作為關鍵字引數。
bytes 和 bytearray 物件上的以下方法具有預設行為,這些行為假設使用 ASCII 相容的二進位制格式,但仍可以透過傳遞適當的引數來用於任意二進位制資料。請注意,本節中的所有 bytearray 方法都不是在原處操作,而是生成新物件。
- bytes.center(width[, fillbyte])¶
- bytearray.center(width[, fillbyte])¶
返回在長度為 width 的序列中居中的物件的副本。填充使用指定的 fillbyte 完成(預設為 ASCII 空格)。對於
bytes
物件,如果 width 小於或等於len(s)
,則返回原始序列。注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
- bytes.ljust(width[, fillbyte])¶
- bytearray.ljust(width[, fillbyte])¶
返回在長度為 width 的序列中左對齊的物件的副本。填充使用指定的 fillbyte 完成(預設為 ASCII 空格)。對於
bytes
物件,如果 width 小於或等於len(s)
,則返回原始序列。注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
- bytes.lstrip([chars])¶
- bytearray.lstrip([chars])¶
返回刪除指定前導位元組的序列的副本。chars 引數是一個二進位制序列,指定要刪除的位元組值集 - 該名稱指的是此方法通常與 ASCII 字元一起使用的事實。如果省略或為
None
,則 chars 引數預設為刪除 ASCII 空格。chars 引數不是字首;而是,其值的所有組合都會被剝離>>> b' spacious '.lstrip() b'spacious ' >>> b'www.example.com'.lstrip(b'cmowz.') b'example.com'
要刪除的位元組值的二進位制序列可以是任何 bytes-like object。有關將刪除單個字首字串而不是一組字元的所有字元的方法,請參閱
removeprefix()
。例如>>> b'Arthur: three!'.lstrip(b'Arthur: ') b'ee!' >>> b'Arthur: three!'.removeprefix(b'Arthur: ') b'three!'
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
- bytes.rjust(width[, fillbyte])¶
- bytearray.rjust(width[, fillbyte])¶
返回在長度為 width 的序列中右對齊的物件的副本。填充使用指定的 fillbyte 完成(預設為 ASCII 空格)。對於
bytes
物件,如果 width 小於或等於len(s)
,則返回原始序列。注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
- bytes.rsplit(sep=None, maxsplit=-1)¶
- bytearray.rsplit(sep=None, maxsplit=-1)¶
使用 sep 作為分隔符字串將二進位制序列分割為相同型別的子序列。如果給定了 maxsplit,則最多執行 maxsplit 次分割,最右側的分割優先。如果未指定 sep 或為
None
,則任何僅由 ASCII 空格組成的子序列都是分隔符。除了從右側分割外,rsplit()
的行為類似於split()
,詳細說明如下。
- bytes.rstrip([chars])¶
- bytearray.rstrip([chars])¶
返回一個刪除了指定尾部位元組的序列副本。chars 引數是一個二進位制序列,指定要刪除的位元組值集合 - 名稱指的是此方法通常與 ASCII 字元一起使用的事實。如果省略或為
None
,則 chars 引數預設為刪除 ASCII 空白字元。chars 引數不是字尾;而是刪除其值的所有組合。>>> b' spacious '.rstrip() b' spacious' >>> b'mississippi'.rstrip(b'ipz') b'mississ'
要刪除的位元組值的二進位制序列可以是任何類位元組物件。有關將刪除單個字尾字串而不是一組字元的方法,請參閱
removesuffix()
。例如>>> b'Monty Python'.rstrip(b' Python') b'M' >>> b'Monty Python'.removesuffix(b' Python') b'Monty'
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
- bytes.split(sep=None, maxsplit=-1)¶
- bytearray.split(sep=None, maxsplit=-1)¶
使用 sep 作為分隔符字串,將二進位制序列拆分為相同型別的子序列。如果給定 maxsplit 且為非負數,則最多完成 maxsplit 次拆分(因此,列表最多將有
maxsplit+1
個元素)。如果未指定 maxsplit 或為-1
,則拆分次數沒有限制(將進行所有可能的拆分)。如果給定了 sep,則連續的分隔符不會分組在一起,並且被視為分隔空子序列(例如,
b'1,,2'.split(b',')
返回[b'1', b'', b'2']
)。sep 引數可以包含多位元組序列作為單個分隔符。使用指定的分隔符拆分空序列會返回[b'']
或[bytearray(b'')]
,具體取決於要拆分的物件型別。sep 引數可以是任何類位元組物件。例如
>>> b'1,2,3'.split(b',') [b'1', b'2', b'3'] >>> b'1,2,3'.split(b',', maxsplit=1) [b'1', b'2,3'] >>> b'1,2,,3,'.split(b',') [b'1', b'2', b'', b'3', b''] >>> b'1<>2<>3<4'.split(b'<>') [b'1', b'2', b'3<4']
如果未指定 sep 或為
None
,則會應用不同的拆分演算法:連續的 ASCII 空白字元序列被視為單個分隔符,並且如果序列具有前導或尾隨空白字元,則結果將不包含開頭或結尾的空字串。因此,拆分空序列或僅由不帶指定分隔符的 ASCII 空白字元組成的序列會返回[]
。例如
>>> b'1 2 3'.split() [b'1', b'2', b'3'] >>> b'1 2 3'.split(maxsplit=1) [b'1', b'2 3'] >>> b' 1 2 3 '.split() [b'1', b'2', b'3']
- bytes.strip([chars])¶
- bytearray.strip([chars])¶
返回一個刪除了指定前導和尾隨位元組的序列副本。chars 引數是一個二進位制序列,指定要刪除的位元組值集合 - 名稱指的是此方法通常與 ASCII 字元一起使用的事實。如果省略或為
None
,則 chars 引數預設為刪除 ASCII 空白字元。chars 引數不是字首或字尾;而是刪除其值的所有組合。>>> b' spacious '.strip() b'spacious' >>> b'www.example.com'.strip(b'cmowz.') b'example'
要刪除的位元組值的二進位制序列可以是任何類位元組物件。
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
bytes 和 bytearray 物件上的以下方法假定使用與 ASCII 相容的二進位制格式,不應應用於任意二進位制資料。請注意,本節中的所有 bytearray 方法都 *不* 在原地操作,而是生成新物件。
- bytes.capitalize()¶
- bytearray.capitalize()¶
返回一個序列副本,其中每個位元組都被解釋為 ASCII 字元,並且第一個位元組大寫,其餘位元組小寫。非 ASCII 位元組值將保持不變。
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
- bytes.expandtabs(tabsize=8)¶
- bytearray.expandtabs(tabsize=8)¶
返回序列的副本,其中所有 ASCII 製表符都被一個或多個 ASCII 空格替換,具體取決於當前列和給定的製表符大小。製表符位置每 tabsize 個位元組出現一次(預設為 8,製表符位置位於列 0、8、16 等)。要展開序列,將當前列設定為零,並逐位元組檢查序列。如果該位元組是 ASCII 製表符(
b'\t'
),則在結果中插入一個或多個空格字元,直到當前列等於下一個製表符位置。(不復制製表符本身。)如果當前位元組是 ASCII 換行符(b'\n'
)或回車符(b'\r'
),則會複製它並將當前列重置為零。無論位元組值在列印時如何表示,都將複製任何其他位元組值且當前列遞增 1。>>> b'01\t012\t0123\t01234'.expandtabs() b'01 012 0123 01234' >>> b'01\t012\t0123\t01234'.expandtabs(4) b'01 012 0123 01234'
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
- bytes.isalnum()¶
- bytearray.isalnum()¶
如果序列中的所有位元組都是字母 ASCII 字元或 ASCII 十進位制數字,並且序列不為空,則返回
True
,否則返回False
。字母 ASCII 字元是序列b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的那些位元組值。ASCII 十進位制數字是序列b'0123456789'
中的那些位元組值。例如
>>> b'ABCabc1'.isalnum() True >>> b'ABC abc1'.isalnum() False
- bytes.isalpha()¶
- bytearray.isalpha()¶
如果序列中的所有位元組都是字母 ASCII 字元,並且序列不為空,則返回
True
,否則返回False
。字母 ASCII 字元是序列b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的那些位元組值。例如
>>> b'ABCabc'.isalpha() True >>> b'ABCabc1'.isalpha() False
- bytes.isascii()¶
- bytearray.isascii()¶
如果序列為空或序列中的所有位元組都是 ASCII,則返回
True
,否則返回False
。ASCII 位元組的範圍是 0-0x7F。在 3.7 版本中新增。
- bytes.isdigit()¶
- bytearray.isdigit()¶
如果序列中的所有位元組都是 ASCII 十進位制數字,並且序列不為空,則返回
True
,否則返回False
。ASCII 十進位制數字是序列b'0123456789'
中的那些位元組值。例如
>>> b'1234'.isdigit() True >>> b'1.23'.isdigit() False
- bytes.islower()¶
- bytearray.islower()¶
如果序列中至少有一個小寫 ASCII 字元,且沒有大寫 ASCII 字元,則返回
True
,否則返回False
。例如
>>> b'hello world'.islower() True >>> b'Hello world'.islower() False
小寫 ASCII 字元是序列
b'abcdefghijklmnopqrstuvwxyz'
中的那些位元組值。大寫 ASCII 字元是序列b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的那些位元組值。
- bytes.isspace()¶
- bytearray.isspace()¶
如果序列中所有位元組都是 ASCII 空白字元且序列不為空,則返回
True
,否則返回False
。ASCII 空白字元是指序列中的以下位元組值:b' \t\n\r\x0b\f'
(空格、製表符、換行符、回車符、垂直製表符、換頁符)。
- bytes.istitle()¶
- bytearray.istitle()¶
如果序列是 ASCII 標題格式且序列不為空,則返回
True
,否則返回False
。有關“標題格式”定義的更多詳細資訊,請參閱bytes.title()
。例如
>>> b'Hello World'.istitle() True >>> b'Hello world'.istitle() False
- bytes.isupper()¶
- bytearray.isupper()¶
如果序列中至少有一個大寫字母 ASCII 字元且沒有小寫 ASCII 字元,則返回
True
,否則返回False
。例如
>>> b'HELLO WORLD'.isupper() True >>> b'Hello world'.isupper() False
小寫 ASCII 字元是序列
b'abcdefghijklmnopqrstuvwxyz'
中的那些位元組值。大寫 ASCII 字元是序列b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的那些位元組值。
- bytes.lower()¶
- bytearray.lower()¶
返回序列的副本,其中所有大寫 ASCII 字元都轉換為對應的小寫字元。
例如
>>> b'Hello World'.lower() b'hello world'
小寫 ASCII 字元是序列
b'abcdefghijklmnopqrstuvwxyz'
中的那些位元組值。大寫 ASCII 字元是序列b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的那些位元組值。注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
- bytes.splitlines(keepends=False)¶
- bytearray.splitlines(keepends=False)¶
返回二進位制序列中行的列表,在 ASCII 行邊界處斷開。此方法使用通用換行符方法來拆分行。除非給出 *keepends* 併為真,否則換行符不包含在結果列表中。
例如
>>> b'ab c\n\nde fg\rkl\r\n'.splitlines() [b'ab c', b'', b'de fg', b'kl'] >>> b'ab c\n\nde fg\rkl\r\n'.splitlines(keepends=True) [b'ab c\n', b'\n', b'de fg\r', b'kl\r\n']
與
split()
不同,當給出分隔符字串 *sep* 時,此方法為空字串返回一個空列表,並且終端換行符不會導致額外的行>>> b"".split(b'\n'), b"Two lines\n".split(b'\n') ([b''], [b'Two lines', b'']) >>> b"".splitlines(), b"One line\n".splitlines() ([], [b'One line'])
- bytes.swapcase()¶
- bytearray.swapcase()¶
返回序列的副本,其中所有小寫 ASCII 字元轉換為對應的大寫字元,反之亦然。
例如
>>> b'Hello World'.swapcase() b'hELLO wORLD'
小寫 ASCII 字元是序列
b'abcdefghijklmnopqrstuvwxyz'
中的那些位元組值。大寫 ASCII 字元是序列b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的那些位元組值。與
str.swapcase()
不同,二進位制版本總是存在bin.swapcase().swapcase() == bin
的情況。大小寫轉換在 ASCII 中是對稱的,即使對於任意 Unicode 程式碼點通常不是這樣。注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
- bytes.title()¶
- bytearray.title()¶
返回二進位制序列的標題格式版本,其中單詞以大寫 ASCII 字元開頭,其餘字元為小寫。未區分大小寫的位元組值保持不變。
例如
>>> b'Hello world'.title() b'Hello World'
小寫 ASCII 字元是指序列中的以下位元組值:
b'abcdefghijklmnopqrstuvwxyz'
。大寫 ASCII 字元是指序列中的以下位元組值:b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
。所有其他位元組值均未區分大小寫。該演算法使用單詞的簡單、與語言無關的定義,即連續字母的組。該定義在許多情況下都適用,但這意味著收縮和所有格中的撇號會形成單詞邊界,這可能不是想要的結果。
>>> b"they're bill's friends from the UK".title() b"They'Re Bill'S Friends From The Uk"
可以使用正則表示式構造撇號的解決方法
>>> import re >>> def titlecase(s): ... return re.sub(rb"[A-Za-z]+('[A-Za-z]+)?", ... lambda mo: mo.group(0)[0:1].upper() + ... mo.group(0)[1:].lower(), ... s) ... >>> titlecase(b"they're bill's friends.") b"They're Bill's Friends."
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
printf
樣式位元組格式化¶
注意
此處描述的格式化操作顯示了各種怪異之處,這些怪異之處導致了許多常見錯誤(例如未能正確顯示元組和字典)。如果要列印的值可能是元組或字典,請將其包裝在元組中。
位元組物件(bytes
/bytearray
)具有一個獨特的內建操作:%
運算子(模)。這也稱為位元組*格式化*或*插值*運算子。給定 format % values
(其中 *format* 是一個位元組物件),*format* 中的 %
轉換說明符將替換為 *values* 的零個或多個元素。效果類似於在 C 語言中使用 sprintf()
。
如果 *format* 需要單個引數,則 *values* 可以是單個非元組物件。[5] 否則,*values* 必須是一個元組,其專案數與格式位元組物件指定的專案數完全相同,或者是一個對映物件(例如,字典)。
轉換說明符包含兩個或多個字元,並具有以下組成部分,這些組成部分必須按此順序出現:
字元
'%'
,它標記說明符的開始。對映鍵(可選),由帶括號的字元序列組成(例如,
(somename)
)。轉換標誌(可選),它會影響某些轉換型別的結果。
最小欄位寬度(可選)。如果指定為
'*'
(星號),則實際寬度從 values 中的元組的下一個元素讀取,並且要轉換的物件位於最小欄位寬度和可選精度之後。精度(可選),以
'.'
(點)後跟精度給出。如果指定為'*'
(星號),則實際精度從 values 中的元組的下一個元素讀取,並且要轉換的值位於精度之後。長度修飾符(可選)。
轉換型別。
當右側引數是字典(或其他對映型別)時,位元組物件中的格式*必須*包含一個帶括號的對映鍵,該鍵緊接在 '%'
字元之後插入到該字典中。對映鍵從對映中選擇要格式化的值。例如
>>> print(b'%(language)s has %(number)03d quote types.' %
... {b'language': b"Python", b"number": 2})
b'Python has 002 quote types.'
在這種情況下,格式中可能不會出現 *
說明符(因為它們需要順序引數列表)。
轉換標誌字元是:
標誌 |
含義 |
---|---|
|
值轉換將使用“替代形式”(如下定義)。 |
|
數值將使用零填充進行轉換。 |
|
轉換後的值將左對齊(如果同時給定,則覆蓋 |
|
(空格)在有符號轉換產生的正數(或空字串)之前應保留一個空格。 |
|
符號字元( |
長度修飾符(h
、l
或 L
)可能存在,但會被忽略,因為它對於 Python 來說不是必需的 —— 因此例如 %ld
與 %d
相同。
轉換型別如下:
轉換 |
含義 |
備註 |
---|---|---|
|
有符號整數十進位制。 |
|
|
有符號整數十進位制。 |
|
|
有符號八進位制值。 |
(1) |
|
已過時的型別 – 它與 |
(8) |
|
有符號十六進位制(小寫)。 |
(2) |
|
有符號十六進位制(大寫)。 |
(2) |
|
浮點指數格式(小寫)。 |
(3) |
|
浮點指數格式(大寫)。 |
(3) |
|
浮點十進位制格式。 |
(3) |
|
浮點十進位制格式。 |
(3) |
|
浮點格式。如果指數小於 -4 或不小於精度,則使用小寫指數格式,否則使用十進位制格式。 |
(4) |
|
浮點格式。如果指數小於 -4 或不小於精度,則使用大寫指數格式,否則使用十進位制格式。 |
(4) |
|
單位元組(接受整數或單位元組物件)。 |
|
|
位元組(任何遵循 緩衝區協議 或具有 |
(5) |
|
|
(6) |
|
位元組(使用 |
(5) |
|
|
(7) |
|
不轉換任何引數,結果為結果中的 |
備註
替代形式會在第一個數字之前插入一個前導八進位制說明符(
'0o'
)。替代形式會在第一個數字之前插入一個前導
'0x'
或'0X'
(取決於使用'x'
還是'X'
格式)。替代形式會使結果始終包含小數點,即使後面沒有數字。
精度決定小數點後的位數,預設為 6。
替代形式會使結果始終包含小數點,並且不會像其他情況一樣刪除尾隨零。
精度決定小數點前後有效數字的位數,預設為 6。
如果精度為
N
,則輸出將截斷為N
個字元。b'%s'
已棄用,但在 3.x 系列中不會刪除。b'%r'
已棄用,但在 3.x 系列中不會刪除。請參閱 PEP 237。
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它總是產生一個新物件,即使沒有進行任何更改。
另請參閱
PEP 461 - 將 % 格式新增到位元組和 bytearray
在 3.5 版本中新增。
記憶體檢視¶
memoryview
物件允許 Python 程式碼訪問支援 緩衝區協議 的物件的內部資料,而無需複製。
- class memoryview(object)¶
建立一個引用 *object* 的
memoryview
。*object* 必須支援緩衝區協議。支援緩衝區協議的內建物件包括bytes
和bytearray
。memoryview
具有*元素*的概念,它是原始 *object* 處理的原子記憶體單元。對於許多簡單型別(如bytes
和bytearray
),元素是單個位元組,但其他型別(如array.array
)可能具有更大的元素。len(view)
等於tolist
的長度,後者是該檢視的巢狀列表表示。 如果view.ndim = 1
,則等於檢視中的元素數量。在 3.12 版本中更改: 如果
view.ndim == 0
,len(view)
現在會引發TypeError
而不是返回 1。itemsize
屬性會給出單個元素中的位元組數。memoryview
支援切片和索引來公開其資料。一維切片將產生一個子檢視。>>> v = memoryview(b'abcefg') >>> v[1] 98 >>> v[-1] 103 >>> v[1:4] <memory at 0x7f3ddc9f4350> >>> bytes(v[1:4]) b'bce'
如果
format
是struct
模組中的原生格式說明符之一,也支援使用整數或整數元組進行索引,並返回具有正確型別的單個元素。 一維 memoryview 可以使用整數或單整數元組進行索引。 多維 memoryview 可以使用恰好為 *ndim* 個整數的元組進行索引,其中 *ndim* 是維數。 零維 memoryview 可以使用空元組進行索引。這是一個使用非位元組格式的示例
>>> import array >>> a = array.array('l', [-11111111, 22222222, -33333333, 44444444]) >>> m = memoryview(a) >>> m[0] -11111111 >>> m[-1] 44444444 >>> m[::2].tolist() [-11111111, -33333333]
如果底層物件是可寫的,則 memoryview 支援一維切片賦值。 不允許調整大小。
>>> data = bytearray(b'abcefg') >>> v = memoryview(data) >>> v.readonly False >>> v[0] = ord(b'z') >>> data bytearray(b'zbcefg') >>> v[1:4] = b'123' >>> data bytearray(b'z123fg') >>> v[2:3] = b'spam' Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: memoryview assignment: lvalue and rvalue have different structures >>> v[2:6] = b'spam' >>> data bytearray(b'z1spam')
格式為 'B'、'b' 或 'c' 的 可雜湊 (只讀)型別的一維 memoryview 也是可雜湊的。 雜湊定義為
hash(m) == hash(m.tobytes())
>>> v = memoryview(b'abcefg') >>> hash(v) == hash(b'abcefg') True >>> hash(v[2:4]) == hash(b'ce') True >>> hash(v[::-2]) == hash(b'abcefg'[::-2]) True
在 3.3 版本中更改: 一維 memoryview 現在可以切片。 格式為 'B'、'b' 或 'c' 的一維 memoryview 現在是 可雜湊 的。
在 3.4 版本中更改: memoryview 現在會自動註冊到
collections.abc.Sequence
。在 3.5 版本中更改: memoryview 現在可以使用整數元組進行索引。
memoryview
有幾個方法-
__eq__
(exporter
)¶ 如果 memoryview 和 PEP 3118 匯出器的形狀等效,並且當使用
struct
語法解釋運算元的各自格式程式碼時,所有對應的值都相等,則它們相等。對於
struct
當前支援的格式字串的子集,tolist()
,如果v.tolist() == w.tolist()
,則v
和w
相等。>>> import array >>> a = array.array('I', [1, 2, 3, 4, 5]) >>> b = array.array('d', [1.0, 2.0, 3.0, 4.0, 5.0]) >>> c = array.array('b', [5, 3, 1]) >>> x = memoryview(a) >>> y = memoryview(b) >>> x == a == y == b True >>> x.tolist() == a.tolist() == y.tolist() == b.tolist() True >>> z = y[::-2] >>> z == c True >>> z.tolist() == c.tolist() True
如果
struct
模組不支援任何格式字串,則物件將始終比較為不相等(即使格式字串和緩衝區內容相同)>>> from ctypes import BigEndianStructure, c_long >>> class BEPoint(BigEndianStructure): ... _fields_ = [("x", c_long), ("y", c_long)] ... >>> point = BEPoint(100, 200) >>> a = memoryview(point) >>> b = memoryview(point) >>> a == point False >>> a == b False
請注意,與浮點數一樣,對於 memoryview 物件,
v is w
不 意味著v == w
。在 3.3 版本中更改: 之前的版本比較原始記憶體,而忽略了專案格式和邏輯陣列結構。
-
tobytes
(order
=
'C'
)¶ 將緩衝區中的資料作為位元組字串返回。這等效於在 memoryview 上呼叫
bytes
建構函式。>>> m = memoryview(b"abc") >>> m.tobytes() b'abc' >>> bytes(m) b'abc'
對於非連續陣列,結果等於展平的列表表示,其中所有元素都轉換為位元組。
tobytes()
支援所有格式字串,包括那些不在struct
模組語法中的字串。3.8 版本新增: order 可以是 {'C', 'F', 'A'}。 當 order 為 'C' 或 'F' 時,原始陣列的資料將轉換為 C 或 Fortran 順序。 對於連續檢視,'A' 返回物理記憶體的精確副本。 特別是,記憶體中的 Fortran 順序會被保留。 對於非連續檢視,資料首先轉換為 C 順序。 order=None 與 order='C' 相同。
-
hex
([sep
[,bytes_per_sep
]])¶ 返回一個字串物件,其中包含緩衝區中每個位元組的兩個十六進位制數字。
>>> m = memoryview(b"abc") >>> m.hex() '616263'
在 3.5 版本中新增。
在 3.8 版本中更改: 與
bytes.hex()
類似,memoryview.hex()
現在支援可選的 sep 和 bytes_per_sep 引數,以便在十六進位制輸出中的位元組之間插入分隔符。
-
tolist
()¶ 將緩衝區中的資料作為元素列表返回。
>>> memoryview(b'abc').tolist() [97, 98, 99] >>> import array >>> a = array.array('d', [1.1, 2.2, 3.3]) >>> m = memoryview(a) >>> m.tolist() [1.1, 2.2, 3.3]
-
toreadonly
()¶ 返回 memoryview 物件的只讀版本。 原始 memoryview 物件保持不變。
>>> m = memoryview(bytearray(b'abc')) >>> mm = m.toreadonly() >>> mm.tolist() [97, 98, 99] >>> mm[0] = 42 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: cannot modify read-only memory >>> m[0] = 43 >>> mm.tolist() [43, 98, 99]
3.8 版本新增。
-
release
()¶ 釋放 memoryview 物件公開的底層緩衝區。 當持有它們的檢視時,許多物件會採取特殊操作(例如,
bytearray
會暫時禁止調整大小);因此,呼叫 release() 有助於儘快刪除這些限制(並釋放任何懸空的資源)。呼叫此方法後,對檢視的任何進一步操作都會引發
ValueError
(除了release()
本身,它可以被多次呼叫)>>> m = memoryview(b'abc') >>> m.release() >>> m[0] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: operation forbidden on released memoryview object
上下文管理協議可用於類似的效果,使用
with
語句>>> with memoryview(b'abc') as m: ... m[0] ... 97 >>> m[0] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: operation forbidden on released memoryview object
3.2 版本新增。
-
cast
(format
[,shape
])¶ 將 memoryview 轉換為新的格式或形狀。 shape 預設為
[byte_length//new_itemsize]
,這意味著結果檢視將是一維的。 返回值是一個新的 memoryview,但緩衝區本身不會被複制。 支援的轉換是 1D -> C-連續 和 C-連續 -> 1D。目標格式限定為
struct
語法中的單個元素原生格式。其中一種格式必須是位元組格式(‘B’、‘b’ 或 ‘c’)。結果的位元組長度必須與原始長度相同。請注意,所有位元組長度可能取決於作業系統。將 1D/long 型別轉換為 1D/無符號位元組型別
>>> import array >>> a = array.array('l', [1,2,3]) >>> x = memoryview(a) >>> x.format 'l' >>> x.itemsize 8 >>> len(x) 3 >>> x.nbytes 24 >>> y = x.cast('B') >>> y.format 'B' >>> y.itemsize 1 >>> len(y) 24 >>> y.nbytes 24
將 1D/無符號位元組型別轉換為 1D/char 型別
>>> b = bytearray(b'zyz') >>> x = memoryview(b) >>> x[0] = b'a' Traceback (most recent call last): ... TypeError: memoryview: invalid type for format 'B' >>> y = x.cast('c') >>> y[0] = b'a' >>> b bytearray(b'ayz')
將 1D/位元組型別轉換為 3D/整數型別,再轉換為 1D/有符號 char 型別
>>> import struct >>> buf = struct.pack("i"*12, *list(range(12))) >>> x = memoryview(buf) >>> y = x.cast('i', shape=[2,2,3]) >>> y.tolist() [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]] >>> y.format 'i' >>> y.itemsize 4 >>> len(y) 2 >>> y.nbytes 48 >>> z = y.cast('b') >>> z.format 'b' >>> z.itemsize 1 >>> len(z) 48 >>> z.nbytes 48
將 1D/無符號 long 型別轉換為 2D/無符號 long 型別
>>> buf = struct.pack("L"*6, *list(range(6))) >>> x = memoryview(buf) >>> y = x.cast('L', shape=[2,3]) >>> len(y) 2 >>> y.nbytes 48 >>> y.tolist() [[0, 1, 2], [3, 4, 5]]
3.3 版本中新增。
在 3.5 版本中更改: 當轉換為位元組檢視時,不再限制源格式。
還有幾個可用的只讀屬性
- obj¶
memoryview 的底層物件
>>> b = bytearray(b'xyz') >>> m = memoryview(b) >>> m.obj is b True
3.3 版本中新增。
- nbytes¶
nbytes == product(shape) * itemsize == len(m.tobytes())
。這是陣列在連續表示中將使用的位元組空間量。它不一定等於len(m)
>>> import array >>> a = array.array('i', [1,2,3,4,5]) >>> m = memoryview(a) >>> len(m) 5 >>> m.nbytes 20 >>> y = m[::2] >>> len(y) 3 >>> y.nbytes 12 >>> len(y.tobytes()) 12
多維陣列
>>> import struct >>> buf = struct.pack("d"*12, *[1.5*x for x in range(12)]) >>> x = memoryview(buf) >>> y = x.cast('d', shape=[3,4]) >>> y.tolist() [[0.0, 1.5, 3.0, 4.5], [6.0, 7.5, 9.0, 10.5], [12.0, 13.5, 15.0, 16.5]] >>> len(y) 3 >>> y.nbytes 96
3.3 版本中新增。
- readonly¶
一個布林值,指示記憶體是否為只讀。
- format¶
一個字串,包含檢視中每個元素的格式(以
struct
模組樣式)。可以從具有任意格式字串的匯出器建立 memoryview,但某些方法(例如tolist()
)僅限於原生單元素格式。在 3.3 版本中更改: 現在根據 struct 模組語法處理格式
'B'
。這意味著memoryview(b'abc')[0] == b'abc'[0] == 97
。
- itemsize¶
memoryview 中每個元素的大小(以位元組為單位)
>>> import array, struct >>> m = memoryview(array.array('H', [32000, 32001, 32002])) >>> m.itemsize 2 >>> m[0] 32000 >>> struct.calcsize('H') == m.itemsize True
- ndim¶
一個整數,指示記憶體表示的多維陣列的維數。
- suboffsets¶
在內部用於 PIL 風格的陣列。該值僅供參考。
-
集合型別 — set
, frozenset
¶
集合物件是不同可雜湊物件的無序集合。常見用途包括成員資格測試、從序列中刪除重複項,以及計算數學運算,例如交集、並集、差集和對稱差集。(有關其他容器,請參閱內建的 dict
、 list
和 tuple
類,以及 collections
模組。)
與其他集合一樣,集合支援 x in set
、len(set)
和 for x in set
。作為無序集合,集合不記錄元素位置或插入順序。因此,集合不支援索引、切片或其他類似序列的行為。
目前有兩種內建的集合型別,set
和 frozenset
。set
型別是可變的 — 可以使用諸如 add()
和 remove()
之類的方法更改內容。由於它是可變的,因此它沒有雜湊值,不能用作字典鍵或另一個集合的元素。frozenset
型別是不可變的且可雜湊的 — 其內容在建立後無法更改;因此,它可以作為字典鍵或另一個集合的元素使用。
非空集合(不是 frozenset)可以透過將用逗號分隔的元素列表放在大括號內來建立,例如:{'jack', 'sjoerd'}
,除了 set
建構函式之外。
兩個類的建構函式的工作方式相同
- class set([iterable])¶
- class frozenset([iterable])¶
返回一個新集合或 frozenset 物件,其元素取自 iterable。集合的元素必須是 可雜湊的。要表示集合的集合,內部集合必須是
frozenset
物件。如果未指定 iterable,則返回一個新的空集合。可以透過多種方式建立集合
使用大括號內用逗號分隔的元素列表:
{'jack', 'sjoerd'}
使用集合推導式:
{c for c in 'abracadabra' if c not in 'abc'}
使用型別建構函式:
set()
、set('foobar')
、set(['a', 'b', 'foo'])
- len(s)
返回集合 s 中的元素數量(s 的基數)。
- x in s
測試 x 是否為 s 的成員。
- x not in s
測試 x 是否不是 s 的成員。
- isdisjoint(other)¶
如果集合與 other 沒有共同的元素,則返回
True
。當且僅當它們的交集為空集時,集合是不相交的。
- issubset(other)¶
- set <= other
測試集合中的每個元素是否都在 other 中。
- set < other
測試集合是否是 other 的真子集,也就是說,
set <= other and set != other
。
- issuperset(other)¶
- set >= other
測試other中的每個元素是否都在集合中。
- set > other
測試該集合是否為other的真超集,即
set >= other and set != other
。
- union(*others)¶
- set | other | ...
返回一個新集合,其中包含該集合和所有其他集合的元素。
- intersection(*others)¶
- set & other & ...
返回一個新集合,其中包含該集合和所有其他集合共有的元素。
- difference(*others)¶
- set - other - ...
返回一個新集合,其中包含在該集合中但不在其他集合中的元素。
- symmetric_difference(other)¶
- set ^ other
返回一個新集合,其中包含在集合或other中但不同時在兩者中的元素。
- copy()¶
返回該集合的淺複製。
注意,
union()
,intersection()
,difference()
,symmetric_difference()
,issubset()
和issuperset()
方法的非運算子版本將接受任何可迭代物件作為引數。相比之下,它們的基於運算子的對應版本要求其引數是集合。這避免了容易出錯的構造,例如set('abc') & 'cbs'
,而推薦使用更易讀的set('abc').intersection('cbs')
。set
和frozenset
都支援集合之間的比較。當且僅當每個集合的每個元素都包含在另一個集合中(每個集合都是另一個集合的子集)時,兩個集合才相等。當且僅當第一個集合是第二個集合的真子集(是子集,但不相等)時,一個集合才小於另一個集合。當且僅當第一個集合是第二個集合的真超集(是超集,但不相等)時,一個集合才大於另一個集合。set
的例項與frozenset
的例項根據其成員進行比較。例如,set('abc') == frozenset('abc')
返回True
,set('abc') in set([frozenset('abc')])
也返回True
。子集和相等性比較並不推廣到全序函式。例如,任何兩個非空的、不相交的集合都不相等,並且彼此都不是子集,因此以下所有都返回
False
:a<b
、a==b
或a>b
。由於集合只定義了部分排序(子集關係),因此
list.sort()
方法對於集合列表的輸出是未定義的。與字典的鍵一樣,集合元素必須是 可雜湊的。
混合
set
例項和frozenset
的二元運算返回第一個運算元的型別。例如:frozenset('ab') | set('bc')
返回frozenset
的例項。下表列出了可用於
set
但不適用於frozenset
的不可變例項的操作。- update(*others)¶
- set |= other | ...
更新集合,新增所有其他集合的元素。
- intersection_update(*others)¶
- set &= other & ...
更新集合,只保留它和所有其他集合中都存在的元素。
- difference_update(*others)¶
- set -= other | ...
更新集合,刪除其他集合中存在的元素。
- symmetric_difference_update(other)¶
- set ^= other
更新集合,只保留在任一集合中存在但不同時在兩者中存在的元素。
- add(elem)¶
將元素elem新增到集合中。
- discard(elem)¶
如果元素elem存在,則從集合中刪除它。
- clear()¶
刪除集合中的所有元素。
注意,
update()
,intersection_update()
,difference_update()
和symmetric_difference_update()
方法的非運算子版本將接受任何可迭代物件作為引數。注意,
__contains__()
,remove()
和discard()
方法的 elem 引數可以是集合。為了支援搜尋等效的 frozenset,會從 elem 建立一個臨時的 frozenset。
對映型別 — dict
¶
對映 物件將 可雜湊 值對映到任意物件。對映是可變物件。目前只有一個標準的對映型別,即字典。(有關其他容器,請參閱內建的 list
,set
和 tuple
類以及 collections
模組。)
字典的鍵幾乎可以是任意值。不可雜湊的值,也就是說,包含列表、字典或其他可變型別(透過值而不是物件標識進行比較)的值不能用作鍵。比較相等的值(例如 1
、 1.0
和 True
)可以互換使用來索引同一個字典條目。
- class dict(**kwargs)¶
- class dict(mapping, **kwargs)
- class dict(iterable, **kwargs)
返回一個由可選的位置引數和可能為空的關鍵字引數集初始化的新字典。
可以透過多種方式建立字典
使用大括號內以逗號分隔的
key: value
對列表:{'jack': 4098, 'sjoerd': 4127}
或{4098: 'jack', 4127: 'sjoerd'}
使用字典推導式:
{}
,{x: x ** 2 for x in range(10)}
使用型別建構函式:
dict()
、dict([('foo', 100), ('bar', 200)])
、dict(foo=100, bar=200)
如果沒有提供位置引數,則建立一個空字典。如果提供了位置引數,並且它定義了一個
keys()
方法,則透過使用該方法返回的每個鍵在引數上呼叫__getitem__()
來建立字典。否則,位置引數必須是一個可迭代物件。可迭代中的每個專案本身必須是一個恰好包含兩個元素的可迭代物件。每個專案的第一個元素成為新字典中的一個鍵,第二個元素成為對應的值。如果一個鍵出現多次,則該鍵的最後一個值將成為新字典中的對應值。如果提供了關鍵字引數,則將關鍵字引數及其值新增到從位置引數建立的字典中。如果要新增的鍵已存在,則關鍵字引數的值將替換位置引數的值。
為了說明這一點,以下示例都返回一個等於
{"one": 1, "two": 2, "three": 3}
的字典>>> a = dict(one=1, two=2, three=3) >>> b = {'one': 1, 'two': 2, 'three': 3} >>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3])) >>> d = dict([('two', 2), ('one', 1), ('three', 3)]) >>> e = dict({'three': 3, 'one': 1, 'two': 2}) >>> f = dict({'one': 1, 'three': 3}, two=2) >>> a == b == c == d == e == f True
在第一個示例中提供關鍵字引數僅適用於作為有效 Python 識別符號的鍵。否則,可以使用任何有效鍵。
這些是字典支援的操作(因此,自定義對映型別也應該支援)
- list(d)
返回字典 *d* 中使用的所有鍵的列表。
- len(d)
返回字典 *d* 中的專案數。
- d[key]
返回字典 *d* 中鍵為 *key* 的項。如果 *key* 不在對映中,則引發
KeyError
。如果 dict 的子類定義了方法
__missing__()
並且 *key* 不存在,則d[key]
操作將使用鍵 *key* 作為引數呼叫該方法。然後,d[key]
操作返回或引發__missing__(key)
呼叫返回或引發的任何內容。沒有其他操作或方法會呼叫__missing__()
。如果未定義__missing__()
,則會引發KeyError
。__missing__()
必須是一個方法;它不能是一個例項變數>>> class Counter(dict): ... def __missing__(self, key): ... return 0 ... >>> c = Counter() >>> c['red'] 0 >>> c['red'] += 1 >>> c['red'] 1
上面的示例顯示了
collections.Counter
的部分實現。collections.defaultdict
使用不同的__missing__
方法。
- d[key] = value
將
d[key]
設定為 *value*。
- del d[key]
從 *d* 中刪除
d[key]
。如果 *key* 不在對映中,則引發KeyError
。
- key in d
如果 *d* 具有鍵 *key*,則返回
True
,否則返回False
。
- key not in d
等效於
not key in d
。
- iter(d)
返回字典鍵的迭代器。這是
iter(d.keys())
的快捷方式。
- clear()¶
刪除字典中的所有項。
- copy()¶
返回字典的淺複製。
- classmethod fromkeys(iterable, value=None, /)¶
建立一個新字典,其鍵來自 *iterable*,值設定為 *value*。
fromkeys()
是一個返回新字典的類方法。*value* 預設為None
。所有值都只引用單個例項,因此對於 *value* 來說,成為一個可變物件(如空列表)通常沒有意義。要獲取不同的值,請改用 字典推導式 。
- get(key, default=None)¶
如果 *key* 在字典中,則返回 *key* 的值,否則返回 *default*。 如果未給定 *default*,則預設為
None
,因此此方法永遠不會引發KeyError
。
- pop(key[, default])¶
如果 *key* 在字典中,則將其移除並返回其值,否則返回 *default*。如果未給出 *default* 且 *key* 不在字典中,則引發
KeyError
異常。
- popitem()¶
從字典中移除並返回一個
(key, value)
對。返回的對按照LIFO順序排列。popitem()
可用於以破壞性的方式迭代字典,這在集合演算法中經常使用。如果字典為空,呼叫popitem()
將引發KeyError
異常。在 3.7 版本中更改: 現在保證 LIFO 順序。在之前的版本中,
popitem()
會返回一個任意的鍵/值對。
- reversed(d)
返回一個字典鍵的反向迭代器。這是
reversed(d.keys())
的快捷方式。3.8 版本新增。
- setdefault(key, default=None)¶
如果 *key* 在字典中,則返回其值。否則,插入 *key*,其值為 *default*,並返回 *default*。*default* 預設為
None
。
- update([other])¶
使用來自 *other* 的鍵/值對更新字典,覆蓋現有鍵。返回
None
。update()
接受具有keys()
方法的另一個物件(在這種情況下,將使用該方法返回的每個鍵呼叫__getitem__()
)或者鍵/值對的可迭代物件(作為元組或其他長度為 2 的可迭代物件)。如果指定了關鍵字引數,則字典將使用這些鍵/值對進行更新:d.update(red=1, blue=2)
。
- values()¶
返回字典值的新的檢視。請參閱檢視物件文件。
一個
dict.values()
檢視與另一個檢視之間的相等性比較將始終返回False
。當將dict.values()
與自身比較時,也適用此規則。>>> d = {'a': 1} >>> d.values() == d.values() False
- d | other
建立一個新的字典,其中包含 *d* 和 *other* 合併的鍵和值,它們都必須是字典。當 *d* 和 *other* 共享鍵時,*other* 的值具有更高的優先順序。
3.9 版本新增。
- d |= other
使用來自 *other* 的鍵和值更新字典 *d*,*other* 可以是 對映 或鍵/值對的可迭代物件。當 *d* 和 *other* 共享鍵時,*other* 的值具有更高的優先順序。
3.9 版本新增。
當且僅當字典具有相同的
(key, value)
對(與順序無關)時,它們才相等。順序比較('<'、'<='、'>='、'>')引發TypeError
異常。字典保留插入順序。請注意,更新鍵不會影響順序。刪除後新增的鍵將插入到末尾。
>>> d = {"one": 1, "two": 2, "three": 3, "four": 4} >>> d {'one': 1, 'two': 2, 'three': 3, 'four': 4} >>> list(d) ['one', 'two', 'three', 'four'] >>> list(d.values()) [1, 2, 3, 4] >>> d["one"] = 42 >>> d {'one': 42, 'two': 2, 'three': 3, 'four': 4} >>> del d["two"] >>> d["two"] = None >>> d {'one': 42, 'three': 3, 'four': 4, 'two': None}
在 3.7 版本中更改: 字典順序保證為插入順序。此行為是 3.6 版本 CPython 的一個實現細節。
字典和字典檢視是可逆的。
>>> d = {"one": 1, "two": 2, "three": 3, "four": 4} >>> d {'one': 1, 'two': 2, 'three': 3, 'four': 4} >>> list(reversed(d)) ['four', 'three', 'two', 'one'] >>> list(reversed(d.values())) [4, 3, 2, 1] >>> list(reversed(d.items())) [('four', 4), ('three', 3), ('two', 2), ('one', 1)]
在 3.8 版本中更改: 字典現在是可逆的。
另請參閱
types.MappingProxyType
可以用於建立 dict
的只讀檢視。
字典檢視物件¶
由 dict.keys()
、dict.values()
和 dict.items()
返回的物件是*檢視物件*。它們提供了字典條目的動態檢視,這意味著當字典更改時,檢視會反映這些更改。
可以迭代字典檢視以產生其各自的資料,並支援成員資格測試
- len(dictview)
返回字典中的條目數。
- iter(dictview)
返回一個迭代器,用於遍歷字典中的鍵、值或條目(表示為
(key, value)
元組)。鍵和值按插入順序迭代。這允許使用
zip()
建立(value, key)
對:pairs = zip(d.values(), d.keys())
。建立相同列表的另一種方法是pairs = [(v, k) for (k, v) in d.items()]
。在迭代檢視時在字典中新增或刪除條目可能會引發
RuntimeError
或無法迭代所有條目。在 3.7 版本中更改: 字典順序保證為插入順序。
- x in dictview
如果 *x* 在基礎字典的鍵、值或條目中,則返回
True
(在後一種情況下,*x* 應為(key, value)
元組)。
- reversed(dictview)
返回字典的鍵、值或條目的反向迭代器。檢視將按照插入的相反順序迭代。
在 3.8 版本中更改: 字典檢視現在是可逆的。
- dictview.mapping
返回一個
types.MappingProxyType
,它封裝了檢視所引用的原始字典。在 3.10 版本中新增。
鍵檢視是類集合的,因為它們的條目是唯一的且是可雜湊的。專案檢視也具有類集合的操作,因為(鍵,值)對是唯一的且鍵是可雜湊的。如果專案檢視中的所有值也都是可雜湊的,則專案檢視可以與其他集合互操作。(值檢視不被視為類集合的,因為條目通常不是唯一的。)對於類集合的檢視,為抽象基類 collections.abc.Set
定義的所有操作(例如,==
、<
或 ^
)都是可用的。在使用集合運算子時,類集合檢視接受任何可迭代物件作為另一個運算元,這與只接受集合作為輸入的集合不同。
字典檢視用法示例
>>> dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}
>>> keys = dishes.keys()
>>> values = dishes.values()
>>> # iteration
>>> n = 0
>>> for val in values:
... n += val
...
>>> print(n)
504
>>> # keys and values are iterated over in the same order (insertion order)
>>> list(keys)
['eggs', 'sausage', 'bacon', 'spam']
>>> list(values)
[2, 1, 1, 500]
>>> # view objects are dynamic and reflect dict changes
>>> del dishes['eggs']
>>> del dishes['sausage']
>>> list(keys)
['bacon', 'spam']
>>> # set operations
>>> keys & {'eggs', 'bacon', 'salad'}
{'bacon'}
>>> keys ^ {'sausage', 'juice'} == {'juice', 'sausage', 'bacon', 'spam'}
True
>>> keys | ['juice', 'juice', 'juice'] == {'bacon', 'spam', 'juice'}
True
>>> # get back a read-only proxy for the original dictionary
>>> values.mapping
mappingproxy({'bacon': 1, 'spam': 500})
>>> values.mapping['spam']
500
上下文管理器型別¶
Python 的 with
語句支援由上下文管理器定義的執行時上下文的概念。這是透過一對方法實現的,這些方法允許使用者定義的類定義一個執行時上下文,該上下文在語句體執行之前進入,並在語句結束時退出。
- contextmanager.__enter__()¶
進入執行時上下文,並返回此物件或與執行時上下文相關的另一個物件。此方法返回的值繫結到使用此上下文管理器的
with
語句的as
子句中的識別符號。一個返回自身的上下文管理器的例子是 檔案物件。檔案物件從 __enter__() 返回自身,以允許在
with
語句中將open()
用作上下文表達式。一個返回相關物件的上下文管理器的例子是由
decimal.localcontext()
返回的上下文管理器。這些管理器將活動的小數上下文設定為原始小數上下文的副本,然後返回該副本。這允許在with
語句的主體中更改當前的小數上下文,而不會影響with
語句之外的程式碼。
- contextmanager.__exit__(exc_type, exc_val, exc_tb)¶
退出執行時上下文,並返回一個布林標誌,指示是否應抑制發生的任何異常。如果在執行
with
語句的主體時發生異常,則引數包含異常型別、值和回溯資訊。否則,所有三個引數都為None
。從此方法返回 true 值將導致
with
語句抑制異常,並繼續執行緊跟在with
語句之後的語句。否則,異常會在此方法執行完成後繼續傳播。在此方法執行期間發生的異常將替換在with
語句主體中發生的任何異常。傳入的異常絕不應顯式地重新引發 - 相反,此方法應返回 false 值,以指示該方法已成功完成,並且不希望抑制引發的異常。這允許上下文管理程式碼輕鬆檢測
__exit__()
方法是否真的失敗。
Python 定義了幾個上下文管理器,以支援輕鬆的執行緒同步、快速關閉檔案或其他物件,以及更簡單地操作活動的小數算術上下文。除了它們對上下文管理協議的實現之外,這些特定型別沒有得到特殊處理。有關示例,請參閱 contextlib
模組。
Python 的 生成器 和 contextlib.contextmanager
裝飾器提供了一種實現這些協議的便捷方法。如果使用 contextlib.contextmanager
裝飾器修飾生成器函式,它將返回一個實現必要的 __enter__()
和 __exit__()
方法的上下文管理器,而不是未修飾的生成器函式產生的迭代器。
請注意,Python/C API 中 Python 物件的型別結構中沒有這些方法的特定槽位。希望定義這些方法的擴充套件型別必須將它們作為普通的 Python 可訪問方法提供。與設定執行時上下文的開銷相比,單個類字典查詢的開銷可以忽略不計。
型別註解型別 — 泛型別名, 聯合¶
泛型別名型別¶
GenericAlias
物件通常透過 下標 類來建立。它們最常與 容器類 一起使用,例如 list
或 dict
。例如,list[int]
是一個 GenericAlias
物件,它是透過使用引數 int
對 list
類進行下標而建立的。GenericAlias
物件主要用於 型別註解。
注意
通常只有當類實現了特殊方法 __class_getitem__()
時,才有可能對類進行下標。
GenericAlias
物件充當 泛型型別 的代理,實現引數化泛型。
對於容器類,提供給類的 下標 的引數可能指示物件包含的元素的型別。例如,set[bytes]
可以在型別註解中用於表示 set
,其中所有元素的型別都是 bytes
。
對於定義了 __class_getitem__()
但不是容器的類,提供給類的下標的引數通常會指示物件上定義的一個或多個方法的返回型別。例如,正則表示式
可以用於 str
資料型別和 bytes
資料型別。
如果
x = re.search('foo', 'foo')
,則x
將是一個 re.Match 物件,其中x.group(0)
和x[0]
的返回值都將是str
型別。我們可以在型別註解中使用GenericAlias
re.Match[str]
來表示這種型別的物件。如果
y = re.search(b'bar', b'bar')
(注意bytes
的b
),則y
也將是re.Match
的例項,但y.group(0)
和y[0]
的返回值都將是bytes
型別。在型別註解中,我們將用re.Match[bytes]
來表示這種型別的 re.Match 物件。
GenericAlias
物件是類 types.GenericAlias
的例項,該類也可以用於直接建立 GenericAlias
物件。
- T[X, Y, ...]
建立一個
GenericAlias
,表示由型別 *X*、*Y* 和更多型別引數化的型別T
,具體取決於所使用的T
。例如,一個期望包含float
元素的list
的函式def average(values: list[float]) -> float: return sum(values) / len(values)
另一個關於對映物件的示例,使用
dict
,它是一種期望兩個型別引數的泛型型別,分別表示鍵型別和值型別。在本例中,該函式期望一個dict
,其鍵型別為str
,值型別為int
。def send_post_request(url: str, body: dict[str, int]) -> None: ...
內建函式isinstance()
和issubclass()
不接受GenericAlias
型別作為它們的第二個引數。
>>> isinstance([1, 2], list[str])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: isinstance() argument 2 cannot be a parameterized generic
Python 執行時不強制執行型別註解。這擴充套件到泛型型別及其型別引數。當從GenericAlias
建立容器物件時,容器中的元素不會根據其型別進行檢查。例如,以下程式碼不推薦使用,但將無錯誤執行。
>>> t = list[str]
>>> t([1, 2, 3])
[1, 2, 3]
此外,引數化的泛型在物件建立過程中會擦除型別引數。
>>> t = list[str]
>>> type(t)
<class 'types.GenericAlias'>
>>> l = t()
>>> type(l)
<class 'list'>
>>> repr(list[int])
'list[int]'
>>> str(list[int])
'list[int]'
泛型容器的__getitem__()
方法會引發異常,以防止像dict[str][str]
這樣的錯誤。
>>> dict[str][str]
Traceback (most recent call last):
...
TypeError: dict[str] is not a generic class
但是,當使用型別變數時,這種表示式是有效的。索引必須具有與GenericAlias
物件的__args__
中的型別變數項一樣多的元素。
>>> from typing import TypeVar
>>> Y = TypeVar('Y')
>>> dict[str, Y][int]
dict[str, int]
標準泛型類¶
以下標準庫類支援引數化泛型。此列表並非詳盡無遺。
GenericAlias
物件的特殊屬性¶
所有引數化的泛型都實現特殊的只讀屬性。
- genericalias.__origin__¶
此屬性指向未引數化的泛型類。
>>> list[int].__origin__ <class 'list'>
- genericalias.__args__¶
此屬性是一個
tuple
(可能長度為 1),其中包含傳遞給泛型類的原始__class_getitem__()
的泛型型別。>>> dict[str, list[int]].__args__ (<class 'str'>, list[int])
- genericalias.__parameters__¶
此屬性是一個延遲計算的元組(可能為空),其中包含在
__args__
中找到的唯一型別變數。>>> from typing import TypeVar >>> T = TypeVar('T') >>> list[T].__parameters__ (~T,)
注意
具有
typing.ParamSpec
引數的GenericAlias
物件在替換後可能沒有正確的__parameters__
,因為typing.ParamSpec
主要用於靜態型別檢查。
- genericalias.__unpacked__¶
一個布林值,如果別名已使用
*
運算子解包(請參閱TypeVarTuple
),則為 true。3.11 版本新增。
另請參閱
- PEP 484 - 型別提示
介紹 Python 的型別註解框架。
- PEP 585 - 標準集合中的型別提示泛型
引入了本地引數化標準庫類的能力,前提是它們實現了特殊的類方法
__class_getitem__()
。- 泛型,使用者定義的泛型和
typing.Generic
有關如何實現可在執行時引數化並可由靜態型別檢查器理解的泛型類的文件。
3.9 版本新增。
聯合型別¶
聯合物件儲存多個型別物件上的|
(按位或)運算的值。這些型別主要用於型別註解。與typing.Union
相比,聯合型別表示式可以使用更簡潔的型別提示語法。
- X | Y | ...
定義一個儲存型別 *X*, *Y* 等的聯合物件。
X | Y
表示 X 或 Y。它等效於typing.Union[X, Y]
。例如,以下函式期望一個型別為int
或float
的引數。def square(number: int | float) -> int | float: return number ** 2
注意
在執行時,不能使用
|
運算子來定義其中一個或多個成員是前向引用的聯合。例如,int | "Foo"
,其中"Foo"
是對尚未定義的類的引用,將在執行時失敗。對於包含前向引用的聯合,請將整個表示式表示為字串,例如"int | Foo"
。
- union_object == other
可以測試聯合物件與其他聯合物件的相等性。詳情
聯合的聯合被展平。
(int | str) | float == int | str | float
冗餘型別會被刪除。
int | str | int == int | str
比較聯合時,會忽略順序。
int | str == str | int
它與
typing.Union
相容。int | str == typing.Union[int, str]
可選型別可以拼寫為與
None
的聯合。str | None == typing.Optional[str]
- isinstance(obj, union_object)
- issubclass(obj, union_object)
對
isinstance()
和issubclass()
的呼叫也支援聯合物件。>>> isinstance("", int | str) True
但是,不能檢查聯合物件中的引數化泛型。
>>> isinstance(1, int | list[int]) # short-circuit evaluation True >>> isinstance([1], int | list[int]) Traceback (most recent call last): ... TypeError: isinstance() argument 2 cannot be a parameterized generic
聯合物件的使用者可見型別可以從 types.UnionType
訪問,並用於 isinstance()
檢查。不能從型別例項化物件。
>>> import types
>>> isinstance(int | str, types.UnionType)
True
>>> types.UnionType()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'types.UnionType' instances
注意
為支援語法 X | Y
,型別物件的 __or__()
方法被新增。如果元類實現了 __or__()
,則 Union 可能會覆蓋它。
>>> class M(type):
... def __or__(self, other):
... return "Hello"
...
>>> class C(metaclass=M):
... pass
...
>>> C | int
'Hello'
>>> int | C
int | C
另請參閱
PEP 604 – 提出了 X | Y
語法和 Union 型別的 PEP。
在 3.10 版本中新增。
其他內建型別¶
直譯器支援幾種其他型別的物件。其中大多數只支援一到兩種操作。
模組¶
模組上唯一特殊的操作是屬性訪問:m.name
,其中 *m* 是一個模組,*name* 訪問 *m* 的符號表中定義的名稱。可以為模組屬性賦值。(請注意,import
語句嚴格來說不是對模組物件的操作;import foo
並不要求存在名為 *foo* 的模組物件,而是要求在某個地方存在名為 *foo* 的模組的(外部)*定義*。)
每個模組的一個特殊屬性是 __dict__
。這是一個包含模組符號表的字典。修改這個字典實際上會改變模組的符號表,但是不能直接賦值給 __dict__
屬性(你可以寫 m.__dict__['a'] = 1
,這將定義 m.a
為 1
,但是你不能寫 m.__dict__ = {}
)。不建議直接修改 __dict__
。
內置於直譯器中的模組是這樣寫的:<module 'sys' (built-in)>
。如果從檔案載入,它們會被寫成 <module 'os' from '/usr/local/lib/pythonX.Y/os.pyc'>
。
類和類例項¶
函式¶
函式物件由函式定義建立。函式物件上的唯一操作是呼叫它:func(argument-list)
。
實際上有兩種函式物件:內建函式和使用者定義的函式。兩者都支援相同的操作(呼叫函式),但實現方式不同,因此物件型別也不同。
有關更多資訊,請參閱 函式定義。
方法¶
方法是使用屬性表示法呼叫的函式。有兩種型別:內建方法(例如列表上的 append()
)和 類例項方法。內建方法在其支援的型別中進行描述。
如果您透過例項訪問一個方法(在類名稱空間中定義的函式),您將獲得一個特殊的物件:一個繫結方法(也稱為例項方法)物件。當呼叫時,它會將 self
引數新增到引數列表中。繫結方法有兩個特殊的只讀屬性:m.__self__
是方法在其上操作的物件,m.__func__
是實現該方法的函式。呼叫 m(arg-1, arg-2, ..., arg-n)
完全等同於呼叫 m.__func__(m.__self__, arg-1, arg-2, ..., arg-n)
。
與函式物件一樣,繫結方法物件支援獲取任意屬性。但是,由於方法屬性實際上儲存在底層函式物件 (method.__func__
) 上,因此不允許在繫結方法上設定方法屬性。嘗試在方法上設定屬性會導致引發 AttributeError
。為了設定方法屬性,您需要在底層函式物件上顯式設定它。
>>> class C:
... def method(self):
... pass
...
>>> c = C()
>>> c.method.whoami = 'my name is method' # can't set on the method
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'method' object has no attribute 'whoami'
>>> c.method.__func__.whoami = 'my name is method'
>>> c.method.whoami
'my name is method'
有關更多資訊,請參閱 例項方法。
程式碼物件¶
程式碼物件由實現使用,以表示“偽編譯”的可執行 Python 程式碼,例如函式體。它們與函式物件不同,因為它們不包含對其全域性執行環境的引用。程式碼物件由內建的 compile()
函式返回,並且可以從函式物件中透過它們的 __code__
屬性提取。另請參閱 code
模組。
訪問 __code__
會引發帶有引數 obj
和 "__code__"
的 審計事件 object.__getattr__
。
可以透過將程式碼物件(而不是源字串)傳遞給內建函式 exec()
或 eval()
來執行或求值程式碼物件。
有關更多資訊,請參閱 標準型別層次結構。
型別物件¶
型別物件表示各種物件型別。物件的型別透過內建函式 type()
訪問。型別上沒有特殊的操作。標準模組 types
定義了所有標準內建型別的名稱。
型別是這樣寫的:<class 'int'>
。
空物件¶
此物件由不顯式返回值函式返回。它不支援任何特殊操作。只有一個空物件,名為 None
(一個內建名稱)。type(None)()
生成相同的單例。
它被寫成 None
。
省略號物件¶
此物件通常用於切片(請參閱 切片)。它不支援任何特殊操作。只有一個省略號物件,名為 Ellipsis
(一個內建名稱)。type(Ellipsis)()
生成 Ellipsis
單例。
它寫作 Ellipsis
或 ...
。
NotImplemented 物件¶
當比較和二進位制運算被要求對它們不支援的型別進行操作時,會返回此物件。有關更多資訊,請參閱比較。只有一個 NotImplemented
物件。type(NotImplemented)()
會生成單例例項。
它寫作 NotImplemented
。
內部物件¶
特殊屬性¶
實現為幾種物件型別添加了一些特殊的只讀屬性,這些屬性在相關的地方有效。 其中一些屬性不會被 dir()
內建函式報告。
- definition.__name__¶
類、函式、方法、描述符或生成器例項的名稱。
- definition.__module__¶
定義類或函式的模組的名稱。
- definition.__doc__¶
類或函式的文件字串,如果未定義則為
None
。
整數字符串轉換長度限制¶
CPython 在 int
和 str
之間進行轉換時有一個全侷限制,以減輕拒絕服務攻擊。此限制僅適用於十進位制或其他非 2 的冪的數字基數。十六進位制、八進位制和二進位制轉換不受限制。該限制可以配置。
CPython 中的 int
型別是以二進位制形式儲存的任意長度的數字(通常稱為“bignum”)。不存在可以線上性時間內將字串轉換為二進位制整數或將二進位制整數轉換為字串的演算法,除非基數是 2 的冪。即使是已知的最佳十進位制演算法也具有亞二次複雜度。轉換像 int('1' * 500_000)
這樣的大值可能在快速 CPU 上花費超過一秒的時間。
限制轉換大小提供了一種避免CVE 2020-10735的實用方法。
當涉及非線性轉換演算法時,該限制適用於輸入或輸出字串中的數字字元數。下劃線和符號不計入限制。
當操作超出限制時,將引發 ValueError
>>> import sys
>>> sys.set_int_max_str_digits(4300) # Illustrative, this is the default.
>>> _ = int('2' * 5432)
Traceback (most recent call last):
...
ValueError: Exceeds the limit (4300 digits) for integer string conversion: value has 5432 digits; use sys.set_int_max_str_digits() to increase the limit
>>> i = int('2' * 4300)
>>> len(str(i))
4300
>>> i_squared = i*i
>>> len(str(i_squared))
Traceback (most recent call last):
...
ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit
>>> len(hex(i_squared))
7144
>>> assert int(hex(i_squared), base=16) == i*i # Hexadecimal is unlimited.
預設限制為 4300 位數字,如 sys.int_info.default_max_str_digits
中所提供。可配置的最低限制為 640 位數字,如 sys.int_info.str_digits_check_threshold
中所提供。
驗證
>>> import sys
>>> assert sys.int_info.default_max_str_digits == 4300, sys.int_info
>>> assert sys.int_info.str_digits_check_threshold == 640, sys.int_info
>>> msg = int('578966293710682886880994035146873798396722250538762761564'
... '9252925514383915483333812743580549779436104706260696366600'
... '571186405732').to_bytes(53, 'big')
...
3.11 版本新增。
受影響的 API¶
該限制僅適用於 int
和 str
或 bytes
之間可能較慢的轉換
int(string)
,預設基數為 10。int(string, base)
,適用於所有非 2 的冪的基數。str(integer)
.repr(integer)
.任何其他轉換為基數 10 的字串轉換,例如
f"{integer}"
、"{}".format(integer)
或b"%d" % integer
。
這些限制不適用於使用線性演算法的函式
int(string, base)
,基數為 2、4、8、16 或 32。用於十六進位制、八進位制和二進位制數的格式規範迷你語言。
配置限制¶
在 Python 啟動之前,您可以使用環境變數或直譯器命令列標誌來配置限制
PYTHONINTMAXSTRDIGITS
,例如PYTHONINTMAXSTRDIGITS=640 python3
將限制設定為 640,或PYTHONINTMAXSTRDIGITS=0 python3
停用限制。-X int_max_str_digits
,例如python3 -X int_max_str_digits=640
sys.flags.int_max_str_digits
包含PYTHONINTMAXSTRDIGITS
或-X int_max_str_digits
的值。如果同時設定了環境變數和-X
選項,則-X
選項優先。值 -1 表示兩者都未設定,因此在初始化期間使用了sys.int_info.default_max_str_digits
的值。
從程式碼中,您可以使用這些 sys
API 檢查當前限制並設定新的限制
sys.get_int_max_str_digits()
和sys.set_int_max_str_digits()
是用於直譯器範圍限制的 getter 和 setter。子直譯器有自己的限制。
有關預設值和最小值的資訊可以在 sys.int_info
中找到
sys.int_info.default_max_str_digits
是編譯時的預設限制。sys.int_info.str_digits_check_threshold
是可接受的限制的最低值(0 除外,它會停用限制)。
3.11 版本新增。
警告
設定較低的限制可能會導致問題。雖然很少見,但確實存在原始碼中包含十進位制整數常量且超過最小閾值的程式碼。設定限制的後果是,包含長於限制的十進位制整數文字的 Python 原始碼在解析期間會遇到錯誤,通常在啟動時、匯入時甚至安裝時 - 任何時候程式碼的最新 .pyc
尚不存在。包含如此大的常量的原始碼的解決方法是將它們轉換為 0x
十六進位制形式,因為它沒有限制。
如果使用較低的限制,請徹底測試您的應用程式。確保您的測試在早期透過環境或標誌設定限制執行,以便它在啟動期間甚至在任何可能呼叫 Python 將 .py
原始檔預編譯為 .pyc
檔案的安裝步驟中都適用。
推薦配置¶
預設的 sys.int_info.default_max_str_digits
對於大多數應用程式來說應該是合理的。如果您的應用程式需要不同的限制,請從您的主入口點使用與 Python 版本無關的程式碼進行設定,因為這些 API 是在 3.12 之前的版本中的安全補丁版本中新增的。
示例
>>> import sys
>>> if hasattr(sys, "set_int_max_str_digits"):
... upper_bound = 68000
... lower_bound = 4004
... current_limit = sys.get_int_max_str_digits()
... if current_limit == 0 or current_limit > upper_bound:
... sys.set_int_max_str_digits(upper_bound)
... elif current_limit < lower_bound:
... sys.set_int_max_str_digits(lower_bound)
如果需要完全停用它,請將其設定為 0
。
腳註