4.6. Sequence Types — list
, tuple
, range
python擁有三種基本的序列類型:lists
, tuples
和range
茵汰。其他的序列類型包括二進制類型(binary data
)和字符串類型(text strings
)將會在其他章節(jié)內(nèi)進行描述.
4.6.1. Common Sequence Operations
下面的操作支持大部分的序列類型滔悉,包括可變類型和不可變類型逛艰。python里提供的collections.abc.Sequence ABC
是為了更容易在自定義序列類型上正確實現(xiàn)這些操作。
這個表格列舉的操作是根據(jù)優(yōu)先級排序的痢艺。在列表里,s
和t
是相同的序列類型。n
,i
,j
是整數(shù)余佃,x
是滿足任何類型限制的任意對象。
in
和not in
操作有相同的優(yōu)先級.
+
和*
操作與相應(yīng)的數(shù)字操作具有相同的優(yōu)先級跨算。[3]
爆土。
Operation | Result | Notes |
---|---|---|
x in s |
True if an item of s is equal to x, else False
|
(1) |
x not in s |
False if an item of s is equal to x, else True
|
(1) |
s + t |
the concatenation of s and t | (6)(7) |
s * n or n * s
|
equivalent to adding s to itself n times | (2)(7) |
s[i] |
ith item of s, origin 0 | (3) |
s[i:j] |
slice of s from i to j | (3)(4) |
s[i:j:k] |
slice of s from i to j with step k | (3)(5) |
len(s) |
length of s | |
min(s) |
smallest item of s | |
max(s) |
largest item of s | |
s.index(x[, i[, j]]) |
index of the first occurrence of x in s (at or after index i and before index j) | (8) |
s.count(x) |
total number of occurrences of x in s |
相同的序列類型還支持比較。具體地說诸蚕,tuple
和list
通過字典順序來比較對應(yīng)的元素步势。這表示如果兩個序列相等,則必須每個對應(yīng)的元素都要相同背犯,而且兩個序列的類型和長度必須相同坏瘩。(想?yún)㈤唽?yīng)的詳細信息,可以參考Comparisons )
標記:
1.x not in s
--> in
和not in
不止用于一般的的包容測試漠魏,一些特殊的序列類型(比如str
,bytes
和bytearray
)也可以使用它們進行包容測試:
>>> "gg" in "eggs"
True
2.s * n or n * s
--> n
小于0
時被視為0
(產(chǎn)生跟s
類型相同的空類型)倔矾。請注意,序列s
里面的item并沒有被copy柱锹,他們被重復引用多次(n
次). 這個問題常常困擾新的python程序員哪自。
考慮以下情況:
>>> lists = [[]] * 3
>>> lists
[[], [], []]
>>> lists[0].append(3)
>>> lists
[[3], [3], [3]]
為什么會發(fā)生這種情況呢,因為[[]]
是一個包含一個[]元素的數(shù)組禁熏,因此[[]] * 3
都是對這個空數(shù)組的相同引用壤巷,修改任意一個元素都會修改這個單獨的列表。
用指針的說法表示就是:創(chuàng)建了一個包含三個指針的數(shù)組瞧毙,這三個指針都指向同一個地址胧华。你可以通過另一種方式創(chuàng)建空數(shù)組:
>>>lists = [[] for i in range(3)]
>>> lists[0].append(3)
>>> lists[1].append(5)
>>> lists[2].append(7)
>>> lists
[[3], [5], [7]]
FAQ條目中提供了進一步的說明如何創(chuàng)建多維列表寄症?.
3.s[i]
,s[i:j]
,s[i:j:k]
--> 如果i 和j是負數(shù),i和j就會使用:len(s) + i
或者 len(s) + j
代替矩动,但是-0
還是0
if i < 0:
i = len(s) + i
if j < 0:
j = len(s) + j
s[i:j]
--> 從i
到j
的對s
的切片被定義為具有索引k
的序列有巧,使得i <= k < j
。如果i
或者j
比len(s)
的長度大铅忿,使用len(s)
代替剪决。如果i
被省略或者i
是None
,使用0
檀训。如果j
被省略或者j
是None
柑潦,使用len(s)
代替。如果i
大于等于j
峻凫,則切片為空渗鬼。s[i:j:k]
-->s
的從i
到j
,具有索引為x = i + n * k
的切片荧琼,其中n: 0 <= n < (j - i) / k
.換句話說譬胎,指數(shù)為:i, i + k, i + 2 * k, i + 3 * k ......
, 當x
達到j
時停止檢索,但是x
不包括j
命锄。
當k
是正數(shù)時堰乔,如果i
或j
比len(s)
大,他們將變?yōu)?減少到)len(s)
脐恩。
當k
是負數(shù)時镐侯,如果i
或j
比len(s)
大,他們將變?yōu)?減少到)len(s)-1
驶冒。
如果i
或者j
被省略或者為None
苟翻,他們將會變成結(jié)束值,結(jié)束值的數(shù)值取決于k
的符號骗污。如下所示:
# k不能等于0
# 如果k=None崇猫,k = 1
if k == None:
k = 1
if k < 0:
i = len(s) - 1
j = 0
if j > 0:
i = 0
j = len(s) - 1
6.s + t
--> 拼接不可變序列總是產(chǎn)生一個新序列。這意味著通過重復連接建立一個序列將在總序列長度中具有二次運行成本需忿。要獲得線性運行時成本诅炉,您必須切換到以下其中一個選項:
* 如果拼接的是str類型,你可以生成一個序列贴谎,并且可以在末尾使用str.join()或?qū)懭胍粋€io.StringIO實例汞扎,并在完成時檢索其值
*如果拼接的是bytes類型,你可以相似的使用bytes.join()或者io.BytesIO擅这,或者你可以使用bytearray代替,bytearray是可變的并且具有有效的分配機制
*如果拼接的是tuple類型景鼠,使用list代替
*如果拼接的是其他類型仲翎,請查看相關(guān)的類文檔
7.s + t
--> 某些序列類型(如range
)僅支持遵循特定模式的項目序列痹扇,因此不支持序列拼接或重復。
-
s.index(x[, i[, j]])
--> 當在s
中沒有找到x
時index
raisesValueError
溯香。不是所有的類型都支持傳遞附加的參數(shù)i
和j
鲫构。這兩個參數(shù)允許有效的搜索序列的子部分。傳遞額外的參數(shù)大致相當于使用s [i:j] .index(x)
玫坛,只是不復制任何數(shù)據(jù)结笨,并且返回的索引是相對于序列的開始而不是切片的開始。
4.6.2. 不可變序列(Immutable Sequence Types)
唯一不可變的序列類型通常實現(xiàn)的操作不是通過可變序列類型實現(xiàn)的湿镀,這是對內(nèi)置的hash()
的支持炕吸。
這種支持允許將不可變序列(如tuple
實例)用作dict
的key
,并存儲在set
和frozenset
實例中勉痴。
嘗試hash包含不可hash的不可變序列將導致TypeError赫模。
4.6.3. 可變序列(Mutable Sequence Types)
下表中的操作是在可變序列類型上定義的。python里提供的collections.abc.MutableSequence ABC
是為了更容易在自定義序列類型上正確實現(xiàn)這些操作蒸矛。
在表中s
是一個可變序列類型的實例瀑罗,t
是任何可迭代的對象,x
是一個任意的對象雏掠,滿足s
施加的任何類型和數(shù)值限制(例如bytearray
只接受滿足值限制'0 <= x <= 255'的整數(shù))斩祭。
Operation | Result | Notes |
---|---|---|
s[i] = x |
item i of s is replaced by x | |
s[i:j] = t |
slice of s from i to j is replaced by the contents of the iterable t | |
del s[i:j] |
same as s[i:j] = []
|
|
s[i:j:k] = t |
the elements of s[i:j:k] are replaced by those of t
|
(1) |
del s[i:j:k] |
removes the elements of s[i:j:k] from the list |
|
s.append(x) |
appends x to the end of the sequence (same ass[len(s):len(s)] = [x] ) |
|
s.clear() |
removes all items from s (same as del s[:] ) |
(5) |
s.copy() |
creates a shallow copy of s (same as s[:] ) |
(5) |
s.extend(t) or s += t
|
extends s with the contents of t (for the most part the same as s[len(s):len(s)] = t ) |
|
s *= n |
updates s with its contents repeated n times | (6) |
s.insert(i, x) |
inserts x into s at the index given by i (same as s[i:i]= [x] ) |
|
s.pop([i]) |
retrieves the item at i and also removes it from s | (2) |
s.remove(x) |
remove the first item from s where s[i] == x
|
(3) |
s.reverse() |
reverses the items of s in place | (4) |
標記:
- 序列
t
的長度必須和切片的長度一樣. - 參數(shù)
i
默認是-1
, 所以默認返回并刪除最后一個元素。 - 當
s
中沒有發(fā)現(xiàn)x
時乡话,remove
raisesValueError
. -
reverse()
方法在倒置大序列時可以節(jié)省空間摧玫。為了提醒用戶它是以副作用的方式運行的,它不會返回相反的順序蚊伞。 - 為了與不支持切片操作的可變?nèi)萜鞯慕涌冢ㄈ?code>dict和set)保持一致席赂,使用了
clear()
和copy()
New in version 3.3:clear()
andcopy()
methods. - 值n是一個整數(shù),或者一個實現(xiàn)了
__index__()
的對象时迫。n為零和負值時表示清除序列颅停。序列中的item不是被復制;它們被多次引用,如Common Sequence Operations下的s * n
所述掠拳。
4.6.4. Lists
數(shù)組是可變序列癞揉,經(jīng)常用于存儲同類項目的集合(精確的相似度因應(yīng)用程序而異)。
class list([iterable])
Lists may be constructed in several ways:
列表可以以幾種方式構(gòu)建:
- 用一對方括號表示一個空數(shù)組:
[]
- 使用方括號溺欧,用逗號分隔item:
[a]
,[a, b, c]
- for循環(huán)一個list(Using a list comprehension):
[x for x in iterable]
- 使用類型構(gòu)造函數(shù):
list()
orlist(iterable)
構(gòu)造函數(shù)list(iterable)
構(gòu)建一個列表,其items和iterable的item相同喊熟,并且item的順序也相同。iterable可能是一個序列姐刁,支持迭代的容器芥牌,也可以是迭代器對象。如果iterable也是一個list聂使,將會copy一個新的list并且返回壁拉,相當于iterable[:]谬俄。如果沒有參數(shù)傳入,創(chuàng)建一個空序列弃理。舉個例子:
>>>list("abc")
['a', 'b', 'c']
>>>list((1, 2, 3))
[1, 2, 3]
>>>list()
[]
許多其他操作也可以創(chuàng)建lists溃论,包括內(nèi)建函數(shù)sorted()
.
list支持所有通用common方法和可變mutable方法(即以上兩個表格里的所有方法)。并且還支持以下的方法:
sort(*, key=None, reverse=False)
這個方法對列表進行排序痘昌,通過<
(大小)比較對list里的item
進行比較钥勋。異常不會被抑制 - 如果任何比較操作失敗,整個排序操作將失斄咎Α(并且列表可能會保留在部分修改狀態(tài))算灸。
>>>l1 = [3, 2, 6, 3, 'xl', 9, 0] # 注意當前l(fā)1的排列順序
>>>l1.sort() # 對l1進行排序sort,報錯
Traceback (most recent call last):
File "xx.py", line 91, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
TypeError: '<' not supported between instances of 'str' and 'int'
>>>l1 # 重新查看l1的數(shù)據(jù)姑子,發(fā)現(xiàn)數(shù)據(jù)的排列順序已經(jīng)改變
[2, 3, 3, 6, 'xl', 9, 0]
sort()
accepts two arguments that can only be passed by keyword (keyword-only arguments):
sort()
接受兩個只能通過關(guān)鍵字傳遞的參數(shù)key
,reverse
key
指定一個用于從每個列表元素提取比較鍵的參數(shù)的函數(shù)(例如key = str.lower
)乎婿。對應(yīng)于列表中每個項目的鍵被計算一次,然后用于整個排序過程街佑。 “None”的默認值意味著列表項直接排序而不需要計算單獨的鍵值谢翎。
>>>l2 = ['5', '9', 9, 8, 7, '3', 1]
>>>l2.sort() # 類型不同,無法比較沐旨,報錯
Traceback (most recent call last):
File "xx.py", line 91, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'str'
>>>l2.sort(key=int) #使用int()作用于每一個元素森逮,然后進行比較
>>>l2
[1, '3', '5', 7, 8, '9', 9]
functools.cmp_to_key()
可用于將2.x風格的cmp
方法轉(zhuǎn)化為key
方法
reverse
是一個布爾值。如果設(shè)置為True
磁携,則列表元素按照相反的順序進行排序(逆序)褒侧。
這種方法在排序大序列時可以有效節(jié)省內(nèi)存空間。為了提醒用戶谊迄,它運行的副作用闷供,此方法不返回排好序的序列(使用[sorted()
)
sort()
方法保證穩(wěn)定。如果確保不會更改比較相等的元素的相對順序统诺,則排序是穩(wěn)定的 - 這對于多次排序很有幫助歪脏。
CPython實現(xiàn)細節(jié):在列表正在排序時,試圖進行變異甚至檢查列表的效果時粮呢,列表是undefined
婿失。CPython實現(xiàn)使得列表在持續(xù)時間內(nèi)顯示為空,并且如果列表在排序過程中發(fā)生了變化,它可以檢測到ValueError
啄寡。
4.6.5. Tuples
元組是不可變的序列豪硅,通常用于存儲異構(gòu)數(shù)據(jù)的集合(例如enumerate()
生成的2元組)。 元組也用于需要存儲不變序列的同類數(shù)據(jù)的情況(例如允許存儲在set
或dict
實例中)挺物。
class tuple([*iterable*])
元組可以通過以下方式創(chuàng)建:
- 使用一對小括號來創(chuàng)建一個空tuple:
()
- 使用一個逗號結(jié)尾的單個tuple:
a,
or(a,)
- 用逗號分隔項目:
a, b, c
or(a, b, c)
- 使用內(nèi)置函數(shù)
tuple()
:tuple()
ortuple(iterable)
構(gòu)造函數(shù)tuple(iterable)
構(gòu)建一個元組懒浮,其元素與iterable
的元素相同且順序相同。iterable
可以是序列识藤,支持迭代的容器嵌溢,也可以是迭代器對象眯牧。如果iterable
已經(jīng)是一個元組蹋岩,返回數(shù)據(jù)不變赖草。例如,tuple('abc')
返回('a'剪个,'b'秧骑,'c')
和tuple([1,2扣囊,3])
返回(1乎折,2,3)
侵歇。如果沒有參數(shù)骂澄,構(gòu)造函數(shù)將創(chuàng)建一個新的空元組``()`。
請注意惕虑,元組實際上是由逗號組成的坟冲,而不是括號。除了在空元組的情況下溃蔫,或當他們需要避免語法歧義時健提,括號是可選的。例如伟叛,f(a私痹,b,c)
是一個帶有三個參數(shù)的函數(shù)調(diào)用统刮,而f((a紊遵,b,c))
是一個以3-tuple作為唯一參數(shù)的函數(shù)調(diào)用侥蒙。
tuple支持所有的通用序列操作
對于數(shù)據(jù)的異質(zhì)集合暗膜,其中通過名稱訪問比由索引訪問更清晰,collections.namedtuple()
可能是一個比簡單的元組對象更合適的選擇辉哥。
4.6.6. Ranges
range
類型表示numbers的不可變序列腹备,并通常用于for
循環(huán)中。
class range(stop)
class range(start, stop[, step])
range
構(gòu)造函數(shù)的參數(shù)必須是整數(shù)(內(nèi)置[int
]或任何實現(xiàn)__index__
特殊方法的對象)碌燕。
如果省略step
參數(shù)咒劲,則默認為1
。
如果省略start
參數(shù)饲齐,則默認為0
钉凌。
如果step
為零,則引發(fā)'ValueError`
對于step > 0
,range
的實例對象r
的內(nèi)容由以下公式確定:r[i] = start + step * i where (i >= 0 and r[i] < stop)
.請注意捂人,這里r[i] < stop
.
對于step < 0
,range
的實例對象r
的內(nèi)容由以下公式確定:r[i] = start + step * i where (i >= 0 and r[i] > stop)
.請注意御雕,這里r[i] > stop
.
# 偽代碼
if step > 0:
int i = 0
while r[i] < stop:
r[i] = start + step * i
i += 1
if step < 0:
int i = 0
while r[i] > stop:
r[i] = start + step * i
i += 1
如果r [0]
不符合值約束矢沿,range
對象將為空。range
確實支持負指數(shù)酸纲,但這些被解釋為從正指數(shù)確定的序列末尾開始的索引捣鲸。(可以參考切片的理解)
range
的元素中包含有大于sys.maxsize
的元素是被允許的,但是一些方法可能會引發(fā)OverflowError
闽坡,比如說len()
Range examples:
>>>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))
[]
范圍實現(xiàn)所有通用序列操作栽惶,除了連接和重復(由于范圍對象只能表示序列遵循嚴格的模式,重復和連接通常會違反該模式)疾嗅。
start
start參數(shù)的值(如果參數(shù)未提供外厂,則為0
)
stop
stop參數(shù)的值
step
step參數(shù)的值(如果參數(shù)未提供,則為1
)
range
類型比list
或tuple
好的一個地方是:一個range
對象將總是采取相同(写小)的內(nèi)存量汁蝶,無論它代表的范圍的大小(因為它只存儲“start”,“stop”和“step”的值论悴,在使用時再根據(jù)需要計算單個項目和子范圍)掖棉。
Range對象支持collections.abc.Sequence ABC
方法,提供諸如包含測試意荤,元素索引查找啊片,切片和負指數(shù)支持等功能:
>>>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
測試range
對象的==和!=
時,將它們作為序列進行比較玖像。也就是說紫谷,如果兩個range
序列對象表示的值相同,則它們被認為是相等的捐寥。 (請注意笤昨,比較相等的兩個范圍對象可能會有不同的start
,stop
和step
.例如range(0)== range(2握恳,1瞒窒,3)
或range(0,3,2)== range(0,4) 乡洼,2)
崇裁。
>>>range(0)
range(0, 0)
>>>range(2, 1, 3)
range(2, 1, 3)
>>>list(range(0))
[]
>>>list(range(2, 1, 3))
[]
在版本3.2中更改:實現(xiàn)序列ABC。支持切片和負指數(shù)束昵。在恒定時間測試[int
]成員的對象拔稳,而不是迭代所有項目。
在版本3.3中更改:定義'=='和'锹雏!='以根據(jù)它們定義的值序列比較范圍對象(而不是根據(jù)對象標識進行比較)巴比。
3.3版新增功能:start
,stop
和step
屬性。
也可以看看
- linspace recipe顯示如何實現(xiàn)適合浮點應(yīng)用程序的惰性版本的范圍
通用序列(common)操作表格摘抄
x in s | True if an item of s is equal to x, else False | (1) |
x not in s | False if an item of s is equal to x, else True | (1) |
s + t | the concatenation of s and t | (6)(7) |
s * n or n * s | equivalent to adding s to itself n times | (2)(7) |
s[i] | ith item of s, origin 0 | (3) |
s[i:j] | slice of s from i to j | (3)(4) |
s[i:j:k] | slice of s from i to j with step k | (3)(5) |
len(s) | length of s | |
min(s) | smallest item of s | |
max(s) | largest item of s | |
s.index(x[, i[, j]]) | index of the first occurrence of x in s (at or after index i and before index j) | (8) |
s.count(x) | total number of occurrences of x in s |
可變序列(mutable)操作表格摘抄
s[i] = x | item i of s is replaced by x | |
s[i:j] = t | slice of s from i to j is replaced by the contents of the iterable t | |
del s[i:j] | same as s[i:j] = [] | |
s[i:j:k] = t | the elements of s[i:j:k] are replaced by those of t | (1) |
del s[i:j:k] | removes the elements of s[i:j:k] from the list | |
s.append(x) | appends x to the end of the sequence (same as s[len(s):len(s)] = [x]) | |
s.clear() | removes all items from s (same as del s[:]) | (5) |
s.copy() | creates a shallow copy of s (same as s[:]) | (5) |
s.extend(t) | or s += t extends s with the contents of t (for the most part the same as s[len(s):len(s)] = t) | |
s *= n | updates s with its contents repeated n times | (6) |
s.insert(i, x) | inserts x into s at the index given by i (same as s[i:i] = [x]) | |
s.pop([i]) | retrieves the item at i and also removes it from s | (2) |
s.remove(x) | remove the first item from s where s[i] == x | (3) |
s.reverse() | reverses the items of s in place | (4) |