內建型別¶
以下各節介紹瞭解釋器內建的標準型別。
主要的內建型別是數字、序列、對映、類、例項和異常。
某些集合類是可變的。那些原地新增、移除或重排成員且不返回特定項的方法,永遠不會返回集合例項本身,而是返回 None
。
許多物件型別支援某些操作;特別是,幾乎所有物件都可以進行相等性比較、真值測試,並轉換為字串(透過 repr()
函式或略有不同的 str()
函式)。後者在物件被 print()
函式寫入時隱式使用。
真值測試¶
任何物件都可以進行真值測試,以用於 if
或 while
條件中,或作為以下布林運算的運算元。
預設情況下,一個物件被認為是真的,除非它的類定義了一個返回 False
的 __bool__()
方法,或者一個返回零的 __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'
會產生一個虛數(實部為零的複數),您可以將其加到一個整數或浮點數上以得到一個具有實部和虛部的複數。
建構函式 int()
, float()
, 和 complex()
可用於生成特定型別的數字。
Python 完全支援混合算術:當一個二元算術運算子的兩個運算元是不同數字型別時,較“窄”型別的運算元會被提升為與另一個運算元相同的型別,其中整數比浮點數窄。複數與實數算術按照常規數學公式定義,例如
x + complex(u, v) = complex(x + u, v)
x * complex(u, v) = complex(x * u, x * v)
不同型別數字之間的比較,就好像在比較這些數字的精確值一樣。[2]
所有數字型別(複數除外)都支援以下操作(有關操作優先順序,請參閱 運算子優先順序)
操作 |
結果 |
備註 |
完整文件 |
---|---|---|---|
|
*x* 和 *y* 的和 |
||
|
*x* 和 *y* 的差 |
||
|
*x* 和 *y* 的積 |
||
|
*x* 除以 *y* 的商 |
||
|
*x* 除以 *y* 的地板商 |
(1)(2) |
|
|
*x* / *y* 的餘數 |
(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* 必須是 位元組類物件 或生成位元組的可迭代物件。
*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 還具有以下附加方法。
- classmethod float.from_number(x)¶
類方法,用於從數字 *x* 返回一個浮點數。
如果引數是整數或浮點數,則返回具有相同值(在 Python 的浮點精度範圍內)的浮點數。如果引數超出 Python 浮點數的範圍,將引發
OverflowError
。對於通用 Python 物件
x
,float.from_number(x)
呼叫x.__float__()
。如果未定義__float__()
,則回退到__index__()
。在 3.14 版本加入。
- float.as_integer_ratio()¶
返回一個整數對,其比率恰好等於原始浮點數。該比率是不可約的,分母為正。對於無窮大,引發
OverflowError
,對於 NaN,引發ValueError
。
- float.is_integer()¶
當浮點例項是有限的且值為整數時返回
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'
複數的附加方法¶
complex
型別實現了 numbers.Complex
抽象基類。 complex
還具有以下附加方法。
- classmethod complex.from_number(x)¶
類方法,用於將數字轉換為複數。
對於通用 Python 物件
x
,complex.from_number(x)
呼叫x.__complex__()
。如果未定義__complex__()
,則回退到__float__()
。如果未定義__float__()
,則回退到__index__()
。在 3.14 版本加入。
數字型別的雜湊¶
對於數字 x
和 y
,可能型別不同,一個要求是 hash(x) == hash(y)
當且僅當 x == y
(有關更多詳細資訊,請參閱 __hash__()
方法文件)。為了在各種數字型別(包括 int
, float
, decimal.Decimal
和 fractions.Fraction
)之間易於實現和高效,Python 對數字型別的雜湊基於一個單一的數學函式,該函式對任何有理數都已定義,因此適用於 int
和 fractions.Fraction
的所有例項,以及 float
和 decimal.Decimal
的所有有限例項。本質上,該函式由模 P
約簡給出,其中 P
是一個固定的素數。 P
的值可透過 Python 的 modulus
屬性(位於 sys.hash_info
中)訪問。
CPython 實現細節: 當前,在 32 位 C long 的機器上使用的素數是 P = 2**31 - 1
,在 64 位 C long 的機器上使用的素數是 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)(8) |
|
從 *i* 到 *j* 的 *s* 的切片 |
(3)(4) |
|
從 *i* 到 *j*、步長為 *k* 的 *s* 的切片 |
(3)(5) |
|
*s* 的長度 |
|
|
*s* 的最小項 |
|
|
*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* 被省略或為None
,則使用0
。如果 *j* 被省略或為None
,則使用len(s)
。如果 *i* 大於或等於 *j*,則切片為空。步長為 *k* 的從 *i* 到 *j* 的 *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
)僅支援遵循特定模式的專案序列,因此不支援序列連線或重複。如果 i 超出序列範圍,則引發
IndexError
。
序列方法
序列型別還支援以下方法
- sequence.count(value, /)¶
返回 value 在 sequence 中出現的總次數。
- sequence.index(value[, start[, stop])¶
返回 value 在 sequence 中首次出現的索引。
如果 value 在 sequence 中未找到,則引發
ValueError
。start 或 stop 引數允許高效地搜尋序列的子部分,從 start 開始,在 stop 結束。這大致相當於
start + sequence[start:stop].index(value)
,只是沒有複製任何資料。注意
並非所有序列型別都支援傳遞 start 和 stop 引數。
不可變序列型別¶
不可變序列型別通常實現的唯一操作是也由可變序列型別實現的操作,即內建 hash()
的支援。
此支援允許不可變序列(例如 tuple
例項)用作 dict
鍵,並存儲在 set
和 frozenset
例項中。
嘗試雜湊包含不可雜湊值的不可變序列將導致 TypeError
。
可變序列型別¶
下表中的操作定義在可變序列型別上。提供了 collections.abc.MutableSequence
ABC,以便更輕鬆地在自定義序列型別上正確實現這些操作。
在表中,s 是可變序列型別的例項,t 是任何可迭代物件,x 是滿足 s 施加的任何型別和值限制的任意物件(例如,bytearray
只接受滿足 0 <= x <= 255
值限制的整數)。
操作 |
結果 |
備註 |
---|---|---|
|
s 的項 i 被 x 替換 |
|
|
刪除 s 的項 i |
|
|
i 到 j 的 s 的切片被可迭代物件 t 的內容替換 |
|
|
從列表中刪除 |
|
|
i:j:k 的 s 的元素被 t 的元素替換 |
(1) |
|
刪除列表中 |
|
|
用 t 的內容擴充套件 s(在大多數情況下與 |
|
|
用重複 n 次的內容更新 s |
(2) |
備註
如果 k 不等於
1
,則 t 必須具有與它所替換的切片相同的長度。值 n 是整數,或實現了
__index__()
的物件。 n 的零和負值會清空序列。序列中的項不會被複制;它們被多次引用,如 常用序列操作 中對s * n
的解釋。
可變序列方法
可變序列型別還支援以下方法
- sequence.append(value, /)¶
將 value 追加到序列末尾。這相當於編寫
seq[len(seq):len(seq)] = [value]
。
- sequence.clear()¶
在 3.3 版本加入。
刪除 sequence 中的所有項。這相當於編寫
del sequence[:]
。
- sequence.copy()¶
在 3.3 版本加入。
建立序列的淺複製。這相當於編寫
sequence[:]
。提示
copy()
方法不是MutableSequence
ABC
的一部分,但大多數具體的MutableSequence
型別都提供了它。
- sequence.extend(iterable, /)¶
用 iterable 的內容擴充套件 sequence。在大多數情況下,這與編寫
seq[len(seq):len(seq)] = iterable
相同。
- sequence.insert(index, value, /)¶
在給定 index 處將 value 插入 sequence。這相當於編寫
sequence[index:index] = [value]
。
- sequence.pop(index=-1, /)¶
檢索 index 處的項,並將其從 sequence 中移除。預設情況下,刪除並返回 sequence 中的最後一項。
- sequence.remove(value, /)¶
刪除 sequence 中第一個滿足
sequence[i] == value
的項。如果 value 在 sequence 中未找到,則引發
ValueError
。
- sequence.reverse()¶
就地反轉 sequence 的項。此方法在反轉大型序列時保持空間經濟性。為了提醒使用者它透過副作用操作,它返回
None
。
列表¶
列表是可變序列,通常用於儲存同質項的集合(其中同質的程度將因應用程式而異)。
- 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=1, /)
範圍建構函式的引數必須是整數(可以是內建的
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
)
range
型別相對於普通 list
或 tuple
的優點是,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 版更改: 實現 Sequence ABC。支援切片和負索引。以恆定時間測試 int
物件是否為成員,而不是迭代所有項。
參見
linspace recipe 展示瞭如何實現適合浮點應用程式的惰性範圍版本。
文字和二進位制序列型別方法摘要¶
下表按類別總結了文字和二進位制序列型別的各種方法。
類別 |
|
|||||||
---|---|---|---|---|---|---|---|---|
格式化 |
||||||||
搜尋和替換 |
||||||||
拆分和連線 |
||||||||
字串分類 |
||||||||
大小寫轉換 |
||||||||
填充和去除 |
||||||||
轉換和編碼 |
||||||||
文字序列型別 — str
¶
Python 中的文字資料使用 str
物件,即字串來處理。字串是 Unicode code point 的不可變序列。字串字面量有多種寫法
單引號:
'allows embedded "double" quotes'
雙引號:
"allows embedded 'single' quotes"
三引號:
'''Three single quotes'''
,"""Three double quotes"""
三引號字串可以跨越多行——所有相關的空格都將包含在字串字面量中。
位於單個表示式中且之間只有空格的字串字面量將被隱式轉換為單個字串字面量。也就是說,("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(*, encoding='utf-8', errors='strict')¶
- class str(object)
- class str(object, encoding, errors='strict')
- class str(object, *, errors)
返回 object 的字串版本。如果未提供 object,則返回空字串。否則,
str()
的行為取決於是否給出了 encoding 或 errors,如下所示。如果未提供 encoding 和 errors,則
str(object)
返回type(object).__str__(object)
,這是 object 的“非正式”或易於列印的字串表示形式。對於字串物件,這是字串本身。如果 object 沒有__str__()
方法,則str()
會回退到返回repr(object)
。如果至少給出了 encoding 或 errors 中的一個,則 object 應該是類位元組物件(例如
bytes
或bytearray
)。在這種情況下,如果 object 是bytes
(或bytearray
)物件,則str(bytes, encoding, errors)
等同於bytes.decode(encoding, errors)
。否則,在呼叫bytes.decode()
之前會獲取緩衝區物件下面的位元組物件。有關緩衝區物件的資訊,請參閱 二進位制序列型別 — bytes, bytearray, memoryview 和 緩衝區協議。在沒有 encoding 或 errors 引數的情況下將
bytes
物件傳遞給str()
屬於第一種情況,返回非正式字串表示(另請參閱 Python 命令列選項-b
)。例如>>> str(b'Zoot!') "b'Zoot!'"
有關
str
類及其方法的更多資訊,請參閱 文字序列型別 — str 和下面的 字串方法 部分。要輸出格式化字串,請參閱 f-strings 和 格式字串語法 部分。此外,請參閱 文字處理服務 部分。
字串方法¶
字串實現了所有 常用 序列操作,以及下面描述的附加方法。
字串還支援兩種字串格式化風格,一種提供了高度的靈活性和可定製性(請參閱 str.format()
、格式字串語法 和 自定義字串格式化),另一種基於 C printf
風格格式化,它處理的類型範圍較窄,並且稍微難以正確使用,但對於它能處理的情況通常速度更快(printf 風格字串格式化)。
文字處理服務 部分的標準庫涵蓋了許多提供各種文字相關實用程式的模組(包括 re
模組中的正則表示式支援)。
- str.capitalize()¶
返回字串的副本,其中第一個字元大寫,其餘字元小寫。
3.8 版更改: 第一個字元現在被轉換為首字母大寫而不是大寫。這意味著像二合字母這樣的字元只會將第一個字母大寫,而不是整個字元。
- str.casefold()¶
返回字串的摺疊大小寫版本。摺疊大小寫的字串可用於不區分大小寫的匹配。
摺疊大小寫類似於小寫,但更具侵略性,因為它旨在刪除字串中的所有大小寫差異。例如,德語小寫字母
'ß'
等同於"ss"
。由於它已經是小寫,lower()
對'ß'
不會有任何操作;casefold()
將其轉換為"ss"
。摺疊大小寫演算法在《Unicode 標準》第 3.13 節“預設大小寫摺疊”中進行了描述。
在 3.3 版本加入。
- str.center(width, fillchar=' ', /)¶
返回長度為 width 的居中字串。填充使用指定的 fillchar(預設為 ASCII 空格)。如果 width 小於或等於
len(s)
,則返回原始字串。例如>>> 'Python'.center(10) ' Python ' >>> 'Python'.center(10, '-') '--Python--' >>> 'Python'.center(4) 'Python'
- str.count(sub[, start[, end]])¶
返回子字串 sub 在範圍 [start, end] 中非重疊出現的次數。可選引數 start 和 end 按切片表示法解釋。
如果 sub 為空,則返回字元之間空字串的數量,即字串長度加一。例如
>>> 'spam, spam, spam'.count('spam') 3 >>> 'spam, spam, spam'.count('spam', 5) 2 >>> 'spam, spam, spam'.count('spam', 5, 10) 1 >>> 'spam, spam, spam'.count('eggs') 0 >>> 'spam, spam, spam'.count('') 17
- str.encode(encoding='utf-8', errors='strict')¶
返回編碼為
bytes
的字串。encoding 預設為
'utf-8'
;有關可能的值,請參閱 標準編碼。errors 控制如何處理編碼錯誤。如果為
'strict'
(預設),則引發UnicodeError
異常。其他可能的值包括'ignore'
、'replace'
、'xmlcharrefreplace'
、'backslashreplace'
以及透過codecs.register_error()
註冊的任何其他名稱。有關詳細資訊,請參閱 錯誤處理程式。出於效能原因,errors 的值不會在實際發生編碼錯誤、Python 開發模式 啟用或使用除錯構建 時進行有效性檢查。例如
>>> encoded_str_to_bytes = 'Python'.encode() >>> type(encoded_str_to_bytes) <class 'bytes'> >>> encoded_str_to_bytes b'Python'
3.1 版更改: 添加了對關鍵字引數的支援。
3.9 版更改: errors 引數的值現在在 Python 開發模式 和 除錯模式 下進行檢查。
- str.endswith(suffix[, start[, end]])¶
如果字串以指定的 suffix 結尾,則返回
True
,否則返回False
。suffix 也可以是要查詢的字尾元組。使用可選的 start,從該位置開始測試。使用可選的 end,在此位置停止比較。使用 start 和 end 相當於str[start:end].endswith(suffix)
。例如>>> 'Python'.endswith('on') True >>> 'a tuple of suffixes'.endswith(('at', 'in')) False >>> 'a tuple of suffixes'.endswith(('at', 'es')) True >>> 'Python is amazing'.endswith('is', 0, 9) True
另請參閱
startswith()
和removesuffix()
。
- str.expandtabs(tabsize=8)¶
返回字串的副本,其中所有制表符都被替換為一個或多個空格,具體取決於當前列和給定的製表符大小。製表符位置每 tabsize 個字元出現一次(預設為 8,製表符位置在列 0、8、16 等處)。要展開字串,當前列設定為零,字串逐個字元進行檢查。如果字元是製表符(
\t
),則在結果中插入一個或多個空格字元,直到當前列等於下一個製表符位置。(製表符本身不復制。)如果字元是換行符(\n
)或回車符(\r
),則複製該字元,並將當前列重置為零。任何其他字元都按原樣複製,並且當前列增加一,而不考慮字元列印時的表示方式。例如>>> '01\t012\t0123\t01234'.expandtabs() '01 012 0123 01234' >>> '01\t012\t0123\t01234'.expandtabs(4) '01 012 0123 01234' >>> print('01\t012\n0123\t01234'.expandtabs(4)) 01 012 0123 01234
- str.find(sub[, start[, end]])¶
返回子字串 sub 在切片
s[start:end]
中首次出現的最低索引。可選引數 start 和 end 按切片表示法解釋。如果未找到 sub,則返回-1
。例如>>> 'spam, spam, spam'.find('sp') 0 >>> 'spam, spam, spam'.find('sp', 5) 6
- str.format(*args, **kwargs)¶
執行字串格式化操作。呼叫此方法的字串可以包含字面文字或由花括號
{}
分隔的替換欄位。每個替換欄位包含位置引數的數字索引,或關鍵字引數的名稱。返回字串的副本,其中每個替換欄位都替換為相應引數的字串值。>>> "The sum of 1 + 2 is {0}".format(1+2) 'The sum of 1 + 2 is 3'
有關可以在格式字串中指定的各種格式選項的說明,請參閱 格式字串語法。
備註
當使用
n
型別格式化數字(int
、float
、complex
、decimal.Decimal
和子類)時(例如,'{:n}'.format(1234)
),該函式會臨時將LC_CTYPE
區域設定為LC_NUMERIC
區域,以解碼localeconv()
的decimal_point
和thousands_sep
欄位(如果它們是非 ASCII 或長度超過 1 位元組),並且LC_NUMERIC
區域與LC_CTYPE
區域不同。此臨時更改會影響其他執行緒。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
。字元c
是字母數字的,如果以下任一返回True
:c.isalpha()
、c.isdecimal()
、c.isdigit()
或c.isnumeric()
。
- str.isalpha()¶
如果字串中的所有字元都是字母並且至少有一個字元,則返回
True
,否則返回False
。字母字元是 Unicode 字元資料庫中定義為“Letter”的字元,即具有通用類別屬性為“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, VULGAR FRACTION ONE FIFTH。形式上,數字字元是那些屬性值為Numeric_Type=Digit
,Numeric_Type=Decimal
或Numeric_Type=Numeric
的字元。
- str.isprintable()¶
如果字串中的所有字元都是可列印字元,則返回
True
;如果字串包含至少一個不可列印字元,則返回False
。這裡的“可列印”是指該字元適合
repr()
用於其輸出;“不可列印”是指repr()
對內建型別會對其進行十六進位制轉義。這不影響寫入sys.stdout
或sys.stderr
的字串的處理。可列印字元是指在 Unicode 字元資料庫(請參閱
unicodedata
)中,其常規類別屬於字母(Letter)、標記(Mark)、數字(Number)、標點(Punctuation)或符號(Symbol)組(L、M、N、P 或 S);再加上 ASCII 空格 0x20。不可列印字元是指屬於分隔符(Separator)或其它(Other)組(Z 或 C)的字元,但不包括 ASCII 空格。
- str.isspace()¶
如果字串中只有空白字元並且至少有一個字元,則返回
True
,否則返回False
。一個字元是空白字元,如果在 Unicode 字元資料庫(請參閱
unicodedata
)中,其常規類別是'Zs'
(“分隔符,空格”),或者其雙向類是'WS'
、'B'
或'S'
之一。
- str.istitle()¶
如果字串是標題化的字串並且至少有一個字元(例如,大寫字元只能跟在非大小寫字元後面,小寫字元只能跟在大小寫字元後面),則返回
True
。否則返回False
。例如:
>>> 'Spam, Spam, Spam'.istitle() True >>> 'spam, spam, spam'.istitle() False >>> 'SPAM, SPAM, SPAM'.istitle() False
另請參閱
title()
。
- 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=None, /)¶
返回字串的一個副本,其中刪除前導字元。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(dict, /)¶
- static str.maketrans(from, to, remove='', /)
此靜態方法返回一個可用於
str.translate()
的翻譯表。如果只有一個引數,則它必須是一個字典,將 Unicode 序數(整數)或字元(長度為 1 的字串)對映到 Unicode 序數、字串(任意長度)或
None
。字元鍵隨後將被轉換為序數。如果有兩個引數,它們必須是等長的字串,並且在生成的字典中,from中的每個字元將對映到to中相同位置的字元。如果存在第三個引數,則它必須是一個字串,該字串中的字元將被對映到結果中的
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=None, /)¶
返回字串的一個副本,其中刪除尾隨字元。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']
如果未指定sep或為
None
且maxsplit為0
,則僅考慮前導的連續空白字元。例如:
>>> "".split(None, 0) [] >>> " ".split(None, 0) [] >>> " foo ".split(maxsplit=0) ['foo ']
- str.splitlines(keepends=False)¶
返回字串中行的列表,按行邊界斷開。除非指定了keepends且其值為真,否則行邊界不會包含在生成的列表中。
此方法根據以下行邊界進行分割。特別是,這些邊界是通用換行符的超集。
表示
描述
\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=None, /)¶
返回字串的一個副本,其中刪除前導和尾隨字元。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."
另請參閱
istitle()
。
- 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'
格式化字串字面量(f-string)¶
在 3.6 版本加入。
版本 3.8 中已更改: 添加了除錯運算子(=
)。
版本 3.12 中已更改: f-string 中的表示式的許多限制已被移除。特別是,現在允許巢狀字串、註釋和反斜槓。
f-string(形式上是格式化字串字面量)是以f
或F
為字首的字串字面量。這種型別的字串字面量允許將任意 Python 表示式嵌入到替換欄位中,替換欄位由花括號({}
)分隔。這些表示式在執行時進行求值,類似於str.format()
,並被轉換為常規的str
物件。例如
>>> who = 'nobody'
>>> nationality = 'Spanish'
>>> f'{who.title()} expects the {nationality} Inquisition!'
'Nobody expects the Spanish Inquisition!'
也可以使用多行 f-string。
>>> f'''This is a string
... on two lines'''
'This is a string\non two lines'
單個開花括號'{'
標記一個替換欄位,它可以包含任何 Python 表示式。
>>> nationality = 'Spanish'
>>> f'The {nationality} Inquisition!'
'The Spanish Inquisition!'
要包含字面量{
或}
,請使用雙括號。
>>> x = 42
>>> f'{{x}} is {x}'
'{x} is 42'
也可以使用函式,以及格式說明符。
>>> from math import sqrt
>>> f'√2 \N{ALMOST EQUAL TO} {sqrt(2):.5f}'
'√2 ≈ 1.41421'
任何非字串表示式都預設使用str()
進行轉換。
>>> from fractions import Fraction
>>> f'{Fraction(1, 3)}'
'1/3'
要使用顯式轉換,請使用!
(感嘆號)運算子,後跟任何有效的格式,這些格式是:
轉換 |
含義 |
---|---|
|
|
|
|
|
例如:
>>> from fractions import Fraction
>>> f'{Fraction(1, 3)!s}'
'1/3'
>>> f'{Fraction(1, 3)!r}'
'Fraction(1, 3)'
>>> question = '¿Dónde está el Presidente?'
>>> print(f'{question!a}')
'\xbfD\xf3nde est\xe1 el Presidente?'
在除錯時,透過使用等號(=
)跟在表示式後面,可以同時查看錶達式及其值。這會保留方括號內的空格,並可與轉換器一起使用。預設情況下,除錯運算子使用repr()
(!r
)轉換。例如
>>> from fractions import Fraction
>>> calculation = Fraction(1, 3)
>>> f'{calculation=}'
'calculation=Fraction(1, 3)'
>>> f'{calculation = }'
'calculation = Fraction(1, 3)'
>>> f'{calculation = !s}'
'calculation = 1/3'
一旦輸出了求值,就可以使用冒號(':'
)後面的格式說明符對其進行格式化。在表示式求值(可能已轉換為字串)後,會使用格式說明符(如果沒有給出格式說明符,則為空字串)呼叫結果的__format__()
方法。然後使用格式化結果作為替換欄位的最終值。例如
>>> from fractions import Fraction
>>> f'{Fraction(1, 7):.6f}'
'0.142857'
>>> f'{Fraction(1, 7):_^+10}'
'___+1/7___'
`printf`風格的字串格式化¶
備註
此處描述的格式化操作表現出各種細微差別,導致許多常見錯誤(例如,無法正確顯示元組和字典)。
使用格式化字串字面量、str.format()
介面或string.Template
可能有助於避免這些錯誤。這些替代方法中的每一種都提供了各自的權衡和優點,如簡潔性、靈活性和/或可擴充套件性。
字串物件有一個獨特內建操作:%
運算子(模)。這也稱為字串格式化或插值運算子。給定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.
在這種情況下,格式中可能不會出現*
規範(因為它們需要順序引數列表)。
轉換標誌字元是:
Flag |
含義 |
---|---|
|
轉換將使用“備用形式”(如下定義)。 |
|
對於數字值,轉換將使用零填充。 |
|
轉換將左對齊(如果兩者都給出,則覆蓋 |
|
(空格)在有符號轉換產生的正數(或空字串)之前應留有一個空格。 |
|
符號字元( |
長度修改符(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=b'')¶
- class bytes(source, encoding, errors='strict')
首先,位元組字面量的語法與字串字面量的語法基本相同,只是添加了一個
b
字首。單引號:
b'still allows embedded "double" quotes'
雙引號:
b"still allows embedded 'single' quotes"
三引號:
b'''3 single quotes'''
,b"""3 double quotes"""
位元組字面量僅允許 ASCII 字元(無論宣告的原始碼編碼如何)。任何大於 127 的二進位制值必須在位元組字面量中使用適當的轉義序列表示。
與字串字面量一樣,位元組字面量也可以使用
r
字首來停用轉義序列的處理。有關各種位元組字面量形式(包括支援的轉義序列)的更多資訊,請參閱字串和位元組字面量。雖然位元組字面量和表示基於 ASCII 文字,但位元組物件實際上表現為整數的不可變序列,其中序列中的每個值都受到限制,即
0 <= x < 256
(嘗試違反此限制將觸發ValueError
)。這樣做是特意的,以強調雖然許多二進位制格式包含基於 ASCII 的元素並且可以有效地使用一些面向文字的演算法進行處理,但這通常不適用於任意二進位制資料(盲目地將文字處理演算法應用於不相容 ASCII 的二進位制資料格式通常會導致資料損壞)。除了字面量形式之外,還可以透過其他多種方式建立位元組物件:
指定長度的零填充位元組物件:
bytes(10)
從整數的可迭代物件:
bytes(range(20))
透過緩衝區協議複製現有二進位制資料:
bytes(obj)
另請參閱bytes內建函式。
由於 2 個十六進位制數字精確對應一個位元組,因此十六進位制數是描述二進位制資料的常用格式。因此,bytes 型別有一個額外的類方法來以該格式讀取資料:
- classmethod fromhex(string, /)¶
此
bytes
類方法返回一個位元組物件,解碼給定的字串物件。字串必須包含每個位元組兩個十六進位制數字,並忽略 ASCII 空白。>>> bytes.fromhex('2Ef0 F1f2 ') b'.\xf0\xf1\xf2'
版本 3.7 中已更改:
bytes.fromhex()
現在會跳過字串中的所有 ASCII 空白,而不僅僅是空格。版本 3.14 中已更改:
bytes.fromhex()
現在接受 ASCIIbytes
和類似位元組的物件作為輸入。
存在一個反向轉換函式,用於將位元組物件轉換為其十六進位制表示。
- hex(*, bytes_per_sep=1)¶
- hex(sep, bytes_per_sep=1)
返回一個字串物件,其中包含例項中每個位元組的兩個十六進位制數字。
>>> 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引數,以在十六進位制輸出的位元組之間插入分隔符。
由於位元組物件是整數序列(類似於元組),對於位元組物件b,b[0]
將是一個整數,而b[0:1]
將是一個長度為 1 的位元組物件。(這與文字字串形成對比,在文字字串中,索引和切片都會生成長度為 1 的字串)
位元組物件的表示使用字面量格式(b'...'
),因為它通常比例如bytes([46, 46, 46])
更有用。您始終可以使用list(b)
將位元組物件轉換為整數列表。
位元組陣列物件¶
- class bytearray(source=b'')¶
- class bytearray(source, encoding, errors='strict')
沒有專門的位元組陣列物件字面量語法,而是始終透過呼叫建構函式來建立它們:
建立空例項:
bytearray()
使用給定長度建立零填充例項:
bytearray(10)
從整數的可迭代物件:
bytearray(range(20))
透過緩衝區協議複製現有二進位制資料:
bytearray(b'Hi!')
由於位元組陣列物件是可變的,因此它們除了位元組和位元組陣列操作中描述的常用位元組和位元組陣列操作外,還支援可變序列操作。
另請參閱bytearray內建函式。
由於 2 個十六進位制數字精確對應一個位元組,因此十六進位制數是描述二進位制資料的常用格式。因此,bytearray 型別有一個額外的類方法來以該格式讀取資料:
- classmethod fromhex(string, /)¶
此
bytearray
類方法返回一個 bytearray 物件,解碼給定的字串物件。字串必須包含每個位元組兩個十六進位制數字,並忽略 ASCII 空白。>>> bytearray.fromhex('2Ef0 F1f2 ') bytearray(b'.\xf0\xf1\xf2')
版本 3.7 中已更改:
bytearray.fromhex()
現在會跳過字串中的所有 ASCII 空白,而不僅僅是空格。版本 3.14 中已更改:
bytearray.fromhex()
現在接受 ASCIIbytes
和類似位元組的物件作為輸入。
存在一個反向轉換函式,用於將 bytearray 物件轉換為其十六進位制表示。
- hex(*, bytes_per_sep=1)¶
- hex(sep, bytes_per_sep=1)
返回一個字串物件,其中包含例項中每個位元組的兩個十六進位制數字。
>>> bytearray(b'\xf0\xf1\xf2').hex() 'f0f1f2'
在 3.5 版本加入。
版本 3.8 中已更改: 與
bytes.hex()
類似,bytearray.hex()
現在支援可選的sep和bytes_per_sep引數,以在十六進位制輸出的位元組之間插入分隔符。
- resize(size, /)¶
將
bytearray
的大小調整為包含size位元組。size必須大於或等於 0。如果
bytearray
需要縮小,則超出size的位元組將被截斷。如果
bytearray
需要增長,則所有新位元組,即超出size的位元組,都將設定為 null 位元組。這等價於:
>>> def resize(ba, size): ... if len(ba) > size: ... del ba[size:] ... else: ... ba += b'\0' * (size - len(ba))
示例:
>>> shrink = bytearray(b'abc') >>> shrink.resize(1) >>> (shrink, len(shrink)) (bytearray(b'a'), 1) >>> grow = bytearray(b'abc') >>> grow.resize(5) >>> (grow, len(grow)) (bytearray(b'abc\x00\x00'), 5)
在 3.14 版本加入。
由於位元組陣列物件是整數序列(類似於列表),對於位元組陣列物件b,b[0]
將是一個整數,而b[0:1]
將是一個長度為 1 的位元組陣列物件。(這與文字字串形成對比,在文字字串中,索引和切片都會生成長度為 1 的字串)
位元組陣列物件的表示使用位元組字面量格式(bytearray(b'...')
),因為它通常比例如bytearray([46, 46, 46])
更有用。您始終可以使用list(b)
將位元組陣列物件轉換為整數列表。
位元組和位元組陣列操作¶
bytes 和 bytearray 物件都支援 通用 序列操作。它們不僅可以與同類型的運算元互操作,還可以與任何 類位元組物件 互操作。由於這種靈活性,它們可以在操作中自由混合而不會導致錯誤。但是,結果的返回型別可能取決於運算元的順序。
備註
bytes 和 bytearray 物件上的方法不接受字串作為引數,就像字串上的方法不接受位元組作為引數一樣。例如,你必須這樣寫:
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]])¶
返回子序列 sub 在範圍 [start, end] 內非重疊出現的次數。可選引數 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()
註冊的任何其他名稱。有關詳細資訊,請參閱 錯誤處理程式。出於效能原因,除非實際發生解碼錯誤,Python 開發模式 已啟用或使用了 除錯構建,否則 errors 的值不會被檢查有效性。
3.1 版更改: 添加了對關鍵字引數的支援。
3.9 版更改: errors 引數的值現在在 Python 開發模式 和 除錯模式 下進行檢查。
- bytes.endswith(suffix[, start[, end]])¶
- bytearray.endswith(suffix[, start[, end]])¶
如果二進位制資料以指定的 suffix 結尾,則返回
True
,否則返回False
。suffix 也可以是用於查詢的字尾元組。使用可選的 start,從該位置開始測試。使用可選的 end,在該位置停止比較。要搜尋的字尾可以是任何 類位元組物件。
- 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, /)¶
返回一個 bytes 或 bytearray 物件,它是 iterable 中二進位制資料序列的連線。如果 iterable 中存在任何不是 類位元組物件(包括
str
物件)的值,則會引發TypeError
。元素之間的分隔符是提供此方法的 bytes 或 bytearray 物件的內容。
- static bytes.maketrans(from, to, /)¶
- static bytearray.maketrans(from, to, /)¶
此靜態方法返回一個可用於
bytes.translate()
的轉換表,該表會將 from 中的每個字元對映到 to 中相同位置的字元;from 和 to 都必須是 類位元組物件 且長度相同。在 3.1 版本加入。
- bytes.partition(sep, /)¶
- bytearray.partition(sep, /)¶
在第一次出現 sep 的位置拆分序列,並返回一個包含分隔符之前的部分、分隔符本身或其 bytearray 副本以及分隔符之後的部分的 3 元組。如果找不到分隔符,則返回一個包含原始序列副本、後跟兩個空 bytes 或 bytearray 物件的 3 元組。
要搜尋的分隔符可以是任何 類位元組物件。
- bytes.replace(old, new, count=-1, /)¶
- bytearray.replace(old, new, count=-1, /)¶
返回序列的副本,其中所有子序列 old 的出現都被 new 替換。如果給出了可選引數 count,則只替換前 count 次出現。
要搜尋的子序列及其替換可以是任何 類位元組物件。
備註
此方法的 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 的位置拆分序列,並返回一個包含分隔符之前的部分、分隔符本身或其 bytearray 副本以及分隔符之後的部分的 3 元組。如果找不到分隔符,則返回一個包含兩個空 bytes 或 bytearray 物件、後跟原始序列副本的 3 元組。
要搜尋的分隔符可以是任何 類位元組物件。
- bytes.startswith(prefix[, start[, end]])¶
- bytearray.startswith(prefix[, start[, end]])¶
如果二進位制資料以指定的 prefix 開頭,則返回
True
,否則返回False
。prefix 也可以是用於查詢的字首元組。使用可選的 start,從該位置開始測試。使用可選的 end,在該位置停止比較。要搜尋的字首可以是任何 類位元組物件。
- 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=b' ', /)¶
- bytearray.center(width, fillbyte=b' ', /)¶
返回一個居中於長度為 width 的序列中的物件的副本。填充使用指定的 fillbyte(預設為 ASCII 空格)。對於
bytes
物件,如果 width 小於或等於len(s)
,則返回原始序列。備註
此方法的 bytearray 版本不會就地操作 - 它始終生成新物件,即使未進行任何更改。
- bytes.ljust(width, fillbyte=b' ', /)¶
- bytearray.ljust(width, fillbyte=b' ', /)¶
返回一個左對齊於長度為 width 的序列中的物件的副本。填充使用指定的 fillbyte(預設為 ASCII 空格)。對於
bytes
物件,如果 width 小於或等於len(s)
,則返回原始序列。備註
此方法的 bytearray 版本不會就地操作 - 它始終生成新物件,即使未進行任何更改。
- bytes.lstrip(bytes=None, /)¶
- bytearray.lstrip(bytes=None, /)¶
返回一個副本,其中刪除了指定的開頭位元組。bytes 引數是一個二進位制序列,指定要刪除的位元組值集合。如果省略或為
None
,則 bytes 引數預設為刪除 ASCII 空白字元。bytes 引數不是字首;而是,其所有值的組合都會被刪除。>>> b' spacious '.lstrip() b'spacious ' >>> b'www.example.com'.lstrip(b'cmowz.') b'example.com'
要刪除的位元組值的二進位制序列可以是任何 類位元組物件。有關刪除單個字首字串而不是一組字元的方法,請參閱
removeprefix()
。例如:>>> b'Arthur: three!'.lstrip(b'Arthur: ') b'ee!' >>> b'Arthur: three!'.removeprefix(b'Arthur: ') b'three!'
備註
此方法的 bytearray 版本不會就地操作 - 它始終生成新物件,即使未進行任何更改。
- bytes.rjust(width, fillbyte=b' ', /)¶
- bytearray.rjust(width, fillbyte=b' ', /)¶
返回一個右對齊於長度為 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(bytes=None, /)¶
- bytearray.rstrip(bytes=None, /)¶
返回一個副本,其中刪除了指定的結尾位元組。bytes 引數是一個二進位制序列,指定要刪除的位元組值集合。如果省略或為
None
,則 bytes 引數預設為刪除 ASCII 空白字元。bytes 引數不是字尾;而是,其所有值的組合都會被刪除。>>> 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(bytes=None, /)¶
- bytearray.strip(bytes=None, /)¶
返回一個副本,其中刪除了指定的開頭和結尾位元組。bytes 引數是一個二進位制序列,指定要刪除的位元組值集合。如果省略或為
None
,則 bytes 引數預設為刪除 ASCII 空白字元。bytes 引數不是字首或字尾;而是,其所有值的組合都會被刪除。>>> 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'
),則將其複製,並將當前列重置為零。任何其他位元組值都將保持不變,並且當前列會增加一個,無論該位元組值在列印時如何表示。>>> 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 且為 true,否則行結尾符不包含在結果列表中。
例如:
>>> 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']
與給出分隔符字串 sep 時的
split()
不同,此方法對於空字串返回空列表,並且尾部換行符不會導致產生額外的行。>>> 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 物件(bytes
/bytearray
)有一個獨特的內建操作:%
運算子(模運算子)。這也被稱為位元組格式化或插值運算子。給定 format % values
(其中 format 是一個 bytes 物件),format 中的 % 轉換說明符會被 values 的零個或多個元素替換。效果類似於 C 語言中的 sprintf()
。
如果 format 需要單個引數,values 可以是單個非元組物件。[5] 否則,values 必須是一個元組,其元素數量與格式 bytes 物件指定的數量完全一致,或者是一個單獨的對映物件(例如,字典)。
轉換規範包含兩個或更多個字元,並具有以下組成部分,它們必須按此順序出現:
標記規範開頭的
'%'
字元。對映鍵(可選),由一系列括號括起來的字元組成(例如,
(somename)
)。轉換標誌(可選),它們會影響某些轉換型別的結果。
最小欄位寬度(可選)。如果指定為
'*'
(星號),則實際寬度將從values中的下一個元素讀取,要轉換的物件將出現在最小欄位寬度和可選精度之後。精度(可選),給出為
'.'
(點)後跟精度。如果指定為'*'
(星號),則實際精度將從values中的下一個元素讀取,要轉換的值將出現在精度之後。長度修改符(可選)。
轉換型別。
當右側引數是字典(或其他對映型別)時,bytes 物件中的格式必須包含一個括號括起來的字典鍵,緊跟在 '%'
字元之後。對映鍵從對映中選擇要格式化的值。例如:
>>> print(b'%(language)s has %(number)03d quote types.' %
... {b'language': b"Python", b"number": 2})
b'Python has 002 quote types.'
在這種情況下,格式中可能不會出現*
規範(因為它們需要順序引數列表)。
轉換標誌字元是:
Flag |
含義 |
---|---|
|
轉換將使用“備用形式”(如下定義)。 |
|
對於數字值,轉換將使用零填充。 |
|
轉換將左對齊(如果兩者都給出,則覆蓋 |
|
(空格)在有符號轉換產生的正數(或空字串)之前應留有一個空格。 |
|
符號字元( |
長度修改符(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 - 為 bytes 和 bytearray 新增 % 格式化。
在 3.5 版本加入。
記憶體檢視¶
memoryview
物件允許 Python 程式碼在不復制的情況下訪問支援 緩衝區協議 的物件的內部資料。
- class memoryview(object)¶
建立引用 object 的
memoryview
。object 必須支援緩衝區協議。內建物件,如bytes
和bytearray
,都支援緩衝區協議。memoryview
具有元素的概念,它是起源物件處理的原子記憶體單元。對於像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 現在可以用整數元組進行索引。
版本 3.14 中已更改: memoryview 現在是泛型型別。
memoryview
有幾個方法:- __eq__(exporter)¶
當使用
struct
語法解釋各自的格式程式碼時,如果 memoryview 和 PEP 3118 匯出器具有等效的形狀且所有對應值相等,則它們相等。對於目前
tolist()
支援的struct
格式字串的子集,v
和w
相等,當且僅當v.tolist() == w.tolist()
。>>> 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
請注意,與浮點數一樣,
v is w
對於 memoryview 物件不意味著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(*, bytes_per_sep=1)¶
- hex(sep, bytes_per_sep=1)
返回一個字串物件,其中緩衝區中的每個位元組都用兩個十六進位制數字表示。
>>> 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, /)¶
- cast(format, shape, /)
將 memoryview 轉換為新的格式或形狀。shape 的預設值是
[byte_length//new_itemsize]
,這意味著結果檢視將是一維的。返回值是一個新的 memoryview,但緩衝區本身不會被複制。支援的轉換包括 1D -> C-contiguous 和 C-contiguous -> 1D。目標格式僅限於
struct
語法中的單個元素本機格式。其中一種格式必須是位元組格式(“B”、“b”或“c”)。結果的位元組長度必須與原始長度相同。請注意,所有位元組長度可能取決於作業系統。將 1D/long 轉換為 1D/unsigned bytes
>>> 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/unsigned bytes 轉換為 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/bytes 轉換為 3D/ints,再轉換為 1D/signed 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/unsigned long 轉換為 2D/unsigned 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 中已更改: 在轉換為位元組檢視時,源格式不再受限制。
- count(value, /)¶
計算 value 出現的次數。
在 3.14 版本加入。
- index(value, start=0, stop=sys.maxsize, /)¶
還有一些只讀屬性可用
- 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 中已更改: 格式
'B'
現在根據 struct 模組語法進行處理。這意味著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 風格的陣列。此值僅供參考。
- c_contiguous¶
一個布林值,指示記憶體是否為 C-contiguous。
在 3.3 版本加入。
- f_contiguous¶
一個布林值,指示記憶體是否為 Fortran contiguous。
在 3.3 版本加入。
- contiguous¶
一個布林值,指示記憶體是否為contiguous。
在 3.3 版本加入。
Set 型別 — set
, frozenset
¶
Set 物件是無序的、不重複的、可雜湊物件的集合。常見用途包括成員資格測試、從序列中刪除重複項以及計算交集、並集、差集和對稱差集等數學運算。(有關其他容器,請參閱內建的 dict
、list
和 tuple
類,以及 collections
模組。)
與所有集合一樣,集合支援 x in set
、len(set)
和 for x in set
。由於是無序集合,集合不記錄元素位置或插入順序。因此,集合不支援索引、切片或其他類序列行為。
目前有兩種內建的集合型別:set
和 frozenset
。set
型別是可變的——內容可以透過 add()
和 remove()
等方法進行更改。由於它是可變的,因此沒有雜湊值,不能用作字典鍵或另一個集合的元素。frozenset
型別是不可變的且可雜湊——建立後其內容無法更改;因此,它可以作為字典鍵或另一個集合的元素。
非空集合(非 frozensets)可以透過將逗號分隔的元素列表放在大括號內建立,例如:{'jack', 'sjoerd'}
,這是一種除了 set
建構函式之外的建立方式。
兩個類的建構函式工作方式相同
- class set(iterable=(), /)¶
- class frozenset(iterable=(), /)¶
返回一個新的 set 或 frozenset 物件,其元素來自 iterable。set 的元素必須是可雜湊的。要表示集合的集合,內部集合必須是
frozenset
物件。如果未指定 iterable,則返回一個空 set。Set 可透過多種方式建立
使用大括號內的逗號分隔的元素列表:
{'jack', 'sjoerd'}
使用 set 推導式:
{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。
Mapping 型別 — dict
¶
Mapping 物件將可雜湊值對映到任意物件。Mappings 是可變物件。目前只有一個標準的 mapping 型別,即字典。(有關其他容器,請參閱內建的 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'}
使用 dict 推導式:
{}
,{x: x ** 2 for x in range(10)}
使用型別建構函式:
dict()
,dict([('foo', 100), ('bar', 200)])
,dict(foo=100, bar=200)
如果未提供位置引數,則建立一個空字典。如果提供了位置引數並且它定義了
keys()
方法,則透過使用該方法返回的每個鍵呼叫引數的__getitem__()
來建立字典。否則,位置引數必須是一個可迭代物件。可迭代物件的每個項本身必須是一個只包含兩個元素的 iterable。每個項的第一個元素成為新字典中的鍵,第二個元素成為相應的值。如果一個鍵出現多次,該鍵的最後一個值將成為新字典中的相應值。如果提供了關鍵字引數,則將關鍵字引數及其值新增到由位置引數建立的字典中。如果要新增的鍵已存在,則關鍵字引數的值將替換來自位置引數的值。
提供關鍵字引數(如第一個示例所示)僅適用於有效的 Python 識別符號作為鍵的情況。否則,可以使用任何有效的鍵。
字典當且僅當它們具有相同的
(key, value)
對時才相等(忽略順序)。順序比較(‘<’, ‘<=’, ‘>=’, ‘>’)會引發TypeError
。為了說明字典建立和相等性,以下所有示例都返回一個與{"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 識別符號作為鍵的情況。否則,可以使用任何有效的鍵。
字典保留插入順序。請注意,更新鍵不會影響順序。刪除後新增的鍵會插入到末尾。
>>> 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 中已更改: 字典順序保證為插入順序。此行為是 CPython 從 3.6 開始的實現細節。
以下是字典支援的操作(因此,自定義對映型別也應支援這些操作)
- 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
實現的一部分。另一個__missing__()
方法由collections.defaultdict
使用。
- 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 是可變物件(如空列表)通常沒有意義。要獲得不同的值,請改用 dict 推導式。
- get(key, default=None, /)¶
如果 key 在字典中,則返回其值;否則返回 default。如果未提供 default,則預設值為
None
,因此此方法永遠不會引發KeyError
。
- pop(key, /)¶
- 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(**kwargs)¶
- update(mapping, /, **kwargs)
- update(iterable, /, **kwargs)
使用來自 mapping 或 iterable 和 kwargs 的鍵/值對更新字典,覆蓋現有鍵。返回
None
。update()
接受帶有keys()
方法的另一個物件(在這種情況下,將使用從方法返回的每個鍵呼叫__getitem__()
)或鍵/值對的可迭代物件(作為元組或其他長度為二的 iterable)。如果指定了關鍵字引數,則字典隨後將使用這些鍵/值對進行更新: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 可以是 mapping 或鍵/值對的 iterable。當 d 和 other 共享鍵時,other 的值具有優先權。
在 3.9 版本中新增。
字典和字典檢視是可逆的。
>>> 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 存在於底層字典的鍵、值或項中(在後一種情況下,x 應為
(key, value)
元組),則返回True
。
- reversed(dictview)
返回字典的鍵、值或項的反向迭代器。檢視將按插入順序的反向迭代。
版本 3.8 中已更改: 字典檢視現在是可逆的。
- dictview.mapping
返回一個
types.MappingProxyType
,它包裝了檢視引用的原始字典。在 3.10 版本加入。
鍵檢視是類似集合的,因為它們的條目是唯一的且可雜湊的。項檢視也具有類似集合的操作,因為 (key, value) 對是唯一的且鍵是可雜湊的。如果項檢視中的所有值也都是可雜湊的,那麼項檢視就可以與其他集合進行互操作。(值檢視不被視為類似集合的,因為其中的條目通常不是唯一的。)對於類似集合的檢視,抽象基類 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
Context Manager 型別¶
Python 的 with
語句支援由 context manager 定義的執行時上下文的概念。這是透過一對方法實現的,這些方法允許使用者定義的類定義一個在語句體執行之前進入、在語句結束時退出的執行時上下文
- contextmanager.__enter__()¶
進入執行時上下文,並返回該物件或與執行時上下文相關的另一個物件。此方法返回的值繫結到使用此 context manager 的
with
語句的as
子句中的識別符號。返回自身的 context manager 的一個例子是檔案物件。檔案物件從 __enter__() 返回自身,以便
open()
可以在with
語句中使用作為上下文表達式。返回相關物件的 context manager 的一個例子是由
decimal.localcontext()
返回的。這些管理器將活動的 decimal 上下文設定為原始 decimal 上下文的副本,然後返回該副本。這允許在with
語句的正文中對當前 decimal 上下文進行更改,而不會影響with
語句外的程式碼。
- contextmanager.__exit__(exc_type, exc_val, exc_tb)¶
退出執行時上下文,並返回一個布林標誌,指示是否應抑制發生的任何異常。如果在執行
with
語句的主體時發生異常,則引數包含異常型別、值和回溯資訊。否則,所有三個引數都為None
。從此方法返回真值將導致
with
語句抑制異常,並繼續執行with
語句之後的下一條語句。否則,在方法完成執行後,異常將繼續傳播。在此方法執行期間發生的異常將替換在with
語句主體中發生的任何異常。引發的異常不應被顯式重新引發——相反,該方法應返回一個假值,以指示該方法已成功完成並且不希望抑制已引發的異常。這允許上下文管理程式碼輕鬆檢測
__exit__()
方法是否實際上失敗。
Python 定義了幾個 context manager 來支援輕鬆的執行緒同步、檔案的及時關閉或其他物件,以及更簡單的活動 decimal 算術上下文操作。具體型別除實現 context management protocol 外,不作特殊處理。有關一些示例,請參閱 contextlib
模組。
Python 的生成器和 contextlib.contextmanager
裝飾器提供了一種方便的方式來實現這些協議。如果一個生成器函式被 contextlib.contextmanager
裝飾器裝飾,它將返回一個實現必要的 __enter__()
和 __exit__()
方法的 context manager,而不是未裝飾的生成器函式產生的迭代器。
請注意,Python/C API 中的 Python 物件型別結構沒有為這些方法設定特定的槽。希望定義這些方法的擴充套件型別必須將它們提供為普通的可 Python 訪問方法。與設定執行時上下文的開銷相比,查詢單個類字典的開銷可以忽略不計。
Type Annotation 型別 — Generic Alias, Union¶
型別註解的核心內建型別是 Generic Alias 和 Union。
Generic Alias 型別¶
GenericAlias
物件通常透過下標一個類來建立。它們最常用於容器類,如 list
或 dict
。例如,list[int]
是透過用引數 int
下標 list
類建立的 GenericAlias
物件。GenericAlias
物件主要用於型別註解。
備註
通常只能下標實現特殊方法 __class_getitem__()
的類。
GenericAlias
物件充當泛型型別的代理,實現*引數化泛型*。
對於容器類,提供給類下標的引數可以指示物件所包含元素的型別。例如,set[bytes]
可用於型別註解,以表示一個所有元素都為 bytes
型別的 set
。
對於定義了 __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
,它是一種通用型別,需要兩個型別引數來表示鍵型別和值型別。在此示例中,該函式需要一個鍵型別為str
、值為int
的dict
。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()
或 str()
會顯示引數化型別。
>>> 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] type(int | str) is typing.Union
可選型別可以拼寫為與
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
聯合物件的使用者可見型別可以從 typing.Union
訪問,並用於 isinstance()
檢查。
>>> import typing
>>> isinstance(int | str, typing.Union)
True
>>> typing.Union()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'typing.Union' instances
備註
型別物件的 __or__()
方法是為了支援 X | Y
語法而新增的。如果元類實現了 __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 版本加入。
版本 3.14 中已更改: Union 物件現在是 typing.Union
的例項。以前,它們是 types.UnionType
的例項,後者仍然是 typing.Union
的別名。
其他內建型別¶
直譯器支援多種其他型別的物件。其中大多數只支援一到兩個操作。
模組¶
模組的唯一特殊操作是屬性訪問: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'>
。
Null 物件¶
此物件由不顯式返回值的方法返回。它不支援任何特殊操作。只有一個 Null 物件,名為 None
(內建名稱)。type(None)()
會產生相同的單例。
它被寫為 None
。
Ellipsis 物件¶
此物件通常用於指示某項被省略。它不支援任何特殊操作。只有一個 Ellipsis 物件,名為 Ellipsis
(內建名稱)。type(Ellipsis)()
會產生 Ellipsis
單例。
它被寫為 Ellipsis
或 ...
。
在典型用法中,...
作為 Ellipsis
物件出現在幾個不同的地方,例如:
作為函式體,而不是 pass 語句。
在第三方庫中,例如 NumPy 的切片和步幅。
Python 還在並非 Ellipsis
物件的地方使用三個點,例如:
最後,Python 文件經常使用三個點來表示省略的內容,即使在也使用它們作為 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)
.任何其他轉換為十進位制的字串,例如
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
。
腳註