[python文法] python進階特性
文章目錄
- [python文法] python進階特性
-
- 一、切片
- 二、疊代
- 三、清單生成式
- 四、生成器
- 五、疊代器
一、切片
- 切片的正常用法不再贅述,除了正常的切片功能,還可以在切片的基礎上每個N個元素取一個;
- 以下是每隔2個元素取一個
l = range(10)
for i in l[::2]:
print(i)
0
2
4
6
8
二、疊代
用for周遊list、tuple等可周遊對象,這種周遊就叫做疊代
在Python中,疊代是通過
for ... in
來完成的,而很多語言比如C語言,疊代list是通過下标完成的,比如Java代碼:
for (i=0; i<list.length; i++) {
n = list[i];
}
- python中隻要是可疊代對象,都可以通過for來周遊;通過collections子產品的Iterable類型判斷是否可疊代
>>> from collections import Iterable
>>> isinstance('abc', Iterable) # str是否可疊代
True
>>> isinstance([1,2,3], Iterable) # list是否可疊代
True
>>> isinstance(123, Iterable) # 整數是否可疊代
False
- Python内置的
函數可以把一個list變成索引-元素對,這樣可以同時擷取到index和valueenumerate
>>> for i, value in enumerate(['A', 'B', 'C']):
... print(i, value)
...
0 A
1 B
2 C
三、清單生成式
簡單的用法就不說了,記錄一些特殊的用法
- 多層循環
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
-
的使用if ... else
-
在for之前時,必須包含else。
因為**
前面的部分是一個表達式,它必須根據for
計算出一個結果**。而表達式:x
,它無法根據x if x % 2 == 0
計算出結果,因為缺少x
,必須加上else
:else
報錯:else
-
>>> [x if x % 2 == 0 for x in range(1, 11)]
File "<stdin>", line 1
[x if x % 2 == 0 for x in range(1, 11)]
^
SyntaxError: invalid syntax
>>> [x if x % 2 == 0 else -x for x in range(1, 11)]
[-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]
- for之後不用
因為for後面是篩選條件,用來判斷目前的x要不要傳回,是以不用elseelse
>>> [x for x in range(1, 11) if x % 2 == 0] [2, 4, 6, 8, 10]
四、生成器
- 生成器的典型特點:按照某種算法推算出來,那循環的過程中不斷推算出後續的元素;不必建立完整的list,進而節省大量的空間;
-
生成器的建立
要建立一個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 0x1022ef630>
- 可以直接用for周遊生成器,不一定非要用next; next還要捕獲最後一個空元素的異常
>>> g = (x * x for x in range(4)) >>> for n in g: ... print(n) ... 0 1 4 9
-
比如,著名的斐波拉契數列(Fibonacci),除第一個和第二個數外,任意一個數都可由前兩個數相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, …
斐波拉契數列用清單生成式寫不出來,但是,用函數把它列印出來卻很容易:
生成器的方式的實作,要把def fib(max): n, a, b = 0, 0, 1 while n < max: print(b) a, b = b, a + b n = n + 1 return 'done'
函數變成generator,隻需要把fib
改為print(b)
就可以了:yield b
如果一個函數定義中包含def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return 'done'
關鍵字,那麼這個函數就不再是一個普通函數,而是一個generator:yield
這裡,最難了解的就是generator和函數的執行流程不一樣。函數是順序執行,遇到>>> f = fib(6) >>> f <generator object fib at 0x104feaaa0>
語句或者最後一行函數語句就傳回。而變成generator的函數,在每次調用return
的時候執行,遇到next()
語句傳回,再次執行時從上次傳回的yield
yield
語句處繼續執行。
但是用
循環調用generator時,發現拿不到generator的for
語句的傳回值。如果想要拿到傳回值,必須捕獲return
錯誤,傳回值包含在StopIteration
的StopIteration
中:value
>>> g = fib(6) >>> while True: ... try: ... x = next(g) ... print('g:', x) ... except StopIteration as e: ... print('Generator return value:', e.value) ... break ... g: 1 g: 1 g: 2 g: 3 g: 5 g: 8 Generator return value: done
五、疊代器
凡是可作用于
for
循環的對象都是
Iterable
(可疊代的)類型;
凡是可作用于
next()
函數的對象都是
Iterator
(疊代器)類型,它們表示一個惰性計算的序列;
集合資料類型如
list
、
dict
、
str
等是
Iterable
但不是
Iterator
,不過可以通過
iter()
函數獲得一個
Iterator
對象。