1. 程式人生 > >Python學習三——高階特性

Python學習三——高階特性

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317568446245b3e1c8837414168bcd2d485e553779e000

Python提供了切片(Slice)操作符

L[0:3]表示,從索引0開始取,直到索引3為止,但不包括索引3。即索引012,正好是3個元素。

如果第一個索引是0,還可以省略:

也可以從索引1開始,取出2個元素出來:

類似的,既然Python支援L[-1]取倒數第一個元素,那麼它同樣支援倒數切片

只寫[:]就可以原樣複製一個list

tuple也是一種list,唯一區別是tuple不可變。因此,tuple也可以用切片操作,只是操作的結果仍是tuple


字串'xxx'也可以看成是一種list,每個元素就是一個字元。因此,字串也可以用切片操作,只是操作結果仍是字串

利用切片操作,實現一個trim()函式,去除字串首尾的空格,注意不要呼叫str的strip()方法:


迭代

因為dict的儲存不是按照list的方式順序排列,所以,迭代出的結果順序很可能不一樣。

dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同時迭代key和value,可以用for k, v in d.items()


如果要對list實現類似Java那樣的下標迴圈怎麼辦?Python內建的enumerate函式可以把一個list變成索引-元素對,這樣就可以在

for迴圈中同時迭代索引和元素本身:



請使用迭代查詢一個list中最小和最大值,並返回一個tuple:


列表生成式


for迴圈其實可以同時使用兩個甚至多個變數,比如dictitems()可以同時迭代key和value:



因此,列表生成式也可以使用兩個變數來生成list:


最後把一個list中所有的字串變成小寫:


使用內建的isinstance函式可以判斷一個變數是不是字串:


生成器

要建立一個generator,有很多種方法。第一種方法很簡單,只要把一個列表生成式的[]改成(),就建立了一個generator:

建立Lg的區別僅在於最外層的[]()L是一個list,而g是一個generator。

我們可以直接打印出list的每一個元素,但我們怎麼打印出generator的每一個元素呢?

如果要一個一個打印出來,可以通過next()函式獲得generator的下一個返回值:

每次呼叫next(g),就計算出g的下一個元素的值,直到計算到最後一個元素,沒有更多的元素時,丟擲StopIteration的錯誤。

我們建立了一個generator後,基本上永遠不會呼叫next(),而是通過for迴圈來迭代它,並且不需要關心StopIteration的錯誤。

generator非常強大。如果推算的演算法比較複雜,用類似列表生成式的for迴圈無法實現的時候,還可以用函式來實現。

比如,著名的斐波拉契數列(Fibonacci),除第一個和第二個數外,任意一個數都可由前兩個數相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

上面的函式和generator僅一步之遙。要把fib函式變成generator,只需要把print(b)改為yield b就可以了:

generator函式的“呼叫”實際返回一個generator物件:

這裡,最難理解的就是generator和函式的執行流程不一樣。函式是順序執行,遇到return語句或者最後一行函式語句就返回。而變成generator的函式,在每次呼叫next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。


for迴圈呼叫generator時,發現拿不到generator的return語句的返回值。如果想要拿到返回值,必須捕獲StopIteration錯誤,返回值包含在StopIterationvalue中:

不懂為何會出錯

楊輝三角練習:


把每一行看做一個list,試寫一個generator,不斷輸出下一行的list:



迭代器

我們已經知道,可以直接作用於for迴圈的資料型別有以下幾種:

一類是集合資料型別,如listtupledictsetstr等;

一類是generator,包括生成器和帶yield的generator function。

這些可以直接作用於for迴圈的物件統稱為可迭代物件:Iterable

可以使用isinstance()判斷一個物件是否是Iterable物件:


而生成器不但可以作用於for迴圈,還可以被next()函式不斷呼叫並返回下一個值,直到最後丟擲StopIteration錯誤表示無法繼續返回下一個值了。

可以被next()函式呼叫並不斷返回下一個值的物件稱為迭代器:Iterator

可以使用isinstance()判斷一個物件是否是Iterator物件:

生成器都是Iterator物件,但listdictstr雖然是Iterable,卻不是Iterator

listdictstrIterable變成Iterator可以使用iter()函式:

你可能會問,為什麼listdictstr等資料型別不是Iterator

這是因為Python的Iterator物件表示的是一個數據流,Iterator物件可以被next()函式呼叫並不斷返回下一個資料,直到沒有資料時丟擲StopIteration錯誤。可以把這個資料流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函式實現按需計算下一個資料,所以Iterator的計算是惰性的,只有在需要返回下一個資料時它才會計算。

凡是可作用於for迴圈的物件都是Iterable型別;

凡是可作用於next()函式的物件都是Iterator型別,它們表示一個惰性計算的序列;

集合資料型別如listdictstr等是Iterable但不是Iterator,不過可以通過iter()函式獲得一個Iterator物件。