1. 程式人生 > >【流暢的python】系列——python數據結構之序列2

【流暢的python】系列——python數據結構之序列2

erro 賦值語句 rev 生成器 們的 概念 memory tuple 默認

文章內容接上篇

三、切片

《流暢的python》的第2章中,對於切片的簡單用法,只是一帶而過:

在 Python 裏,像列表(list)、元組(tuple)和字符串(str)這類序列類型都支持切片操作,但是實際上切片操作比人們所想象的要強大很多。

文中,主要講了切片的3個方面:

1.為什麽在python中,切片和區間會忽略最後一個元素(即左閉右開)

2.對象的切片

3.給切片賦值

另外,還提及了多維切片和省略

3.1、為什麽在python中,切片和區間會忽略最後一個元素(即左閉右開)

在切片和區間操作裏不包含區間範圍的最後一個元素是 Python 的風格,這個習慣符合Python、C 和其他語言裏以 0 作為起始下標的傳統。這樣做帶來的好處如下。
1.當只有最後一個位置信息時,我們也可以快速看出切片和區間裏有幾個元素:range(3) 和 my_list[:3] 都返回 3 個元素。
2.當起止位置信息都可見時,我們可以快速計算出切片和區間的長度,用後一個數減去第一個下標(stop - start)即可。
3.這樣做也讓我們可以利用任意一個下標來把序列分割成不重疊的兩部分,只要寫成my_list[:x] 和 my_list[x:] 就可以了

3.2、對對象切片

我們還可以用 s[a:b:c] 的形式對 s 在 a 和 b 之間以 c 為間隔取值。c 的值還可以為負,負值意味著反向取值。

也就是說,c為步長。

>>> s = bicycle
>>> s[::3]
bye
>>> s[::-1]
elcycib
>>> s[::-2]
eccb

3.3、給切片賦值

如果把切片放在賦值語句的左邊,或把它作為 del 操作的對象,我們就可以對序列進行嫁接、切除或就地修改操作。

>>> l = list(range(10))
>>> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l[2:5] = [20, 30] >>> l [0, 1, 20, 30, 5, 6, 7, 8, 9] >>> del l[5:7] >>> l [0, 1, 20, 30, 5, 8, 9] >>> l[3::2] = [11, 22] >>> l [0, 1, 20, 11, 5, 22, 9] >>> l[2:5] = 100 Traceback (most recent call last): File
"<stdin>", line 1, in <module> TypeError: can only assign an iterable >>> l[2:5] = [100] >>> l [0, 1, 100, 22, 9]

四、對序列使用+和*

Python 程序員會默認序列是支持 + 和 * 操作的。通常 + 號兩側的序列由相同類型的數據所構成,在拼接的過程中,兩個被操作的序列都不會被修改,Python 會新建一個包含同樣類型數據的序列來作為拼接的結果。

劃重點就是:

+ 和 * 都遵循這個規律,不修改原有的操作對象,而是構建一個全新的

>>> l = [1, 2, 3]
>>> l * 5
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> 5 * abcd
abcdabcdabcdabcdabcd

五、序列的增量賦值

增量賦值運算符 += 和 *= 的表現取決於它們的第一個操作對象。簡單起見,我們把討論集中在增量加法(+=)上,但是這些概念對 *= 和其他增量運算符來說都是一樣的。
+= 背後的特殊方法是 __iadd__ (用於“就地加法”)。但是如果一個類沒有實現這個方法的話,Python 會退一步調用 __add__ 。考慮下面這個簡單的表達式:

>>> a += b

如果 a 實現了 __iadd__ 方法,就會調用這個方法。同時對可變序列(例如list、bytearray 和 array.array)來說,a 會就地改動,就像調用了 a.extend(b)一樣。但是如果 a 沒有實現 __iadd__ 的話,a += b 這個表達式的效果就變得跟 a = a+ b 一樣了:首先計算 a + b,得到一個新的對象,然後賦值給 a。也就是說,在這個表達式中,變量名會不會被關聯到新的對象,完全取決於這個類型有沒有實 __iadd__ 這個方法。
總體來講,可變序列一般都實現 __iadd__ 方法,因此 += 是就地加法。而不可變序列根本就不支持這個操作,對這個方法的實現也就無從談起。
上面所說的這些關於 += 的概念也適用於 *=,不同的是,後者相對應的是 __imul__。關於 __iadd__ 和 __imul__,第 13 章中會再次提及。

書中的這段原話,揭示了在python中,a += b 和 a = a + b 是有區別的。

六、 排序

list.sort 方法會就地排序列表,也就是說不會把原列表復制一份。

內置函數 sorted,它會新建一個列表作為返回值。這個方法可以接受任何形式的可叠代對象作為參數,甚至包括不可變序列或生成器(見第 14 章)。而不管 sorted 接受的是怎樣的參數,它最後都會返回一個列表

兩個可選的參數

reverse 和key

reverse這個參數的默認值是False,但如果你把它設置成True,那麽,就會以降序的形式輸出。

key這個參數表示以什麽標準來排序,比如,可以是 key = str.lower,也可以是key = len 等等

七、用bisect來管理已排序的

這個小節沒看懂,就不多說了

八、array.array ,memoryview,numpy,collections.deque

array用來存放數字,比list更高效,因為 array.array在底層存儲的是字節表述。

另外,數組還提供從文件讀取和存入文件的更快的方法,如 .frombytes 和 .tofile。

memoryview能讓用戶在不復制內容的情況下操作同一個數組的不同切片。是一個內置類

numpy庫是一個非常優秀的第三方庫,是學習pandas庫的基礎。

第二章就簡單的到這裏了,有些知識點我也沒怎麽看懂,可能將來用到了才會懂吧

【流暢的python】系列——python數據結構之序列2