再一次重新學習Python——高階特性
-
切片
L[0:3]
表示,從索引0開始取,直到索引3為止,但不包括索引3。即索引0,1,2,正好是3個元素。如果第一個索引是0,還可以省略。
同樣支援倒數切片
>>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
>>> L[-2:]
['Bob', 'Jack']
>>> L[-2:-1]
['Bob']
記住倒數第一個元素的索引是-1
。
前10個數,每兩個取一個:
>>> L[:10:2]
[0, 2, 4, 6, 8]
甚至什麼都不寫,只寫[:]
就可以原樣複製一個list。
tuple也是一種list,唯一區別是tuple不可變。因此,tuple也可以用切片操作,只是操作的結果仍是tuple:
>>> (0, 1, 2, 3, 4, 5)[:3]
(0, 1, 2)
字串'xxx'
或Unicode字串u'xxx'
也可以看成是一種list,每個元素就是一個字元。因此,字串也可以用切片操作,只是操作結果仍是字串:
>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[::2]
'ACEG'
-
迭代
dict和字串這種沒有下標的資料型別也可以進行迭代
>>> d = {'a': 1, 'b': 2, 'c': 3} >>> for key in d: ... print key ... a c b
因為dict的儲存不是按照list的方式順序排列,所以,迭代出的結果順序很可能不一樣。
預設情況下,dict迭代的是key。如果要迭代value,可以用for value in d.itervalues()
,如果要同時迭代key和value,可以用for k, v in d.iteritems()
。
由於字串也是可迭代物件,因此,也可以作用於for
迴圈:
>>> for ch in 'ABC':
... print ch
...
A
B
C
通過collections模組的Iterable型別判斷某物件是否為可迭代的物件。
Python內建的enumerate
for
迴圈中同時迭代索引和元素本身:
>>> for i, value in enumerate(['A', 'B', 'C']):
... print i, value
...
0 A
1 B
2 C
上面的for
迴圈裡,同時引用了兩個變數,在Python裡是很常見的,比如下面的程式碼:
>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
... print x, y
...
1 1
2 4
3 9
enumerate() 方法的語法:
enumerate(sequence, [start=0])
引數
- sequence -- 一個序列、迭代器或其他支援迭代物件。
- start -- 下標起始位置。
返回值
返回 enumerate(列舉) 物件。
-
列表生成式
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
for迴圈後面還可以加上if判斷,這樣我們就可以篩選出僅偶數的平方:
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
還可以使用兩層迴圈,可以生成全排列:
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
兩個變數
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.iteritems()]
['y=B', 'x=A', 'z=C']
把一個list中所有的字串變成小寫:
>>> L = ['Hello', 'World', 'IBM', 'Apple']
>>> [s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']
-
生成器
如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必建立完整的list,從而節省大量的空間。在Python中,這種一邊迴圈一邊計算的機制,稱為生成器(Generator)。
建立生成器的方法
第一種方法很簡單,只要把一個列表生成式的[]
改成()
,就建立了一個generator:
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x104feab40>
建立L
和g
的區別僅在於最外層的[]
和()
,L
是一個list,而g
是一個generator。
怎麼打印出generator的每一個元素呢?
如果要一個一個打印出來,可以通過generator的next()
方法:
>>> g.next()
0
>>> g.next()
1
正確的方法是使用for
迴圈,因為generator也是可迭代物件
g = (x * x for x in range(10))
>>> for n in g:
print n
如果一個函式定義中包含yield
關鍵字,那麼這個函式就不再是一個普通函式,而是一個generator
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
最難理解的就是generator和函式的執行流程不一樣。函式是順序執行,遇到return語句或者最後一行函式語句就返回。而變成generator的函式,在每次呼叫next()
的時候執行,遇到yield
語句返回,再次執行時從上次返回的yield
語句處繼續執行。
要理解generator的工作原理,它是在for
迴圈的過程中不斷計算出下一個元素,並在適當的條件結束for
迴圈。對於函式改成的generator來說,遇到return語句或者執行到函式體最後一行語句,就是結束generator的指令,for
迴圈隨之結束。