1、切片(slice)
L[0:3]表示,從索引0開始取,直到索引3為止,但不包括索引3。即索引0,1,2,正好是3個元素。
如果第一個索引是0,還可以省略: L[:3]
也可以從索引1開始,取出2個元素出來:L[1:3]
前10個數,每兩個取一個:L[:10:2]
所有數,每5個取一個:L[::5]
tuple也是一種list,唯一區別是tuple不可變。因此,tuple也可以用切片操作,只是操作的結果仍是tuple:
字符串'xxx'也可以看成是一種list,每個元素就是一個字符。因此,字符串也可以用切片操作,只是操作結果仍是字符串:
2、迭代(iteration)
在Python中,迭代是通過for ... in來完成的,因為Python的for循環不僅可以用在list或tuple上,還可以作用在其他可迭代對象上。
list這種數據類型雖然有下標,但很多其他數據類型是沒有下標的,但是,只要是可迭代對象,無論有無下標,都可以迭代,比如dict就可以迭代:
d = {'a' : 1, 'b' : 2, 'c' : 3} \#迭代key值 for key in d: print(key) \#迭代value值 for value in d.values(): print(value) \#迭代key value for k,v in d.items(): print(k, v)
結果:
a b c 1 2 3 a 1 b 2 c 3 [Finished in 0.1s]
如何判斷一個對象是可迭代對象呢?方法是通過collections模塊的Iterable類型判斷:
from collections import Iterable s1 = isinstance('abc', Iterable) s2 = isinstance([1,2,3],Iterable) s3 = isinstance(123,Iterable) print(s1, s2, s3)
結果:
True True False [Finished in 0.1s]
如果要對list實現類似Java那樣的下標循環怎么辦?Python內置的enumerate函數可以把一個list變成索引-元素對,這樣就可以在for循環中同時迭代索引和元素本身:
for i, value in enumerate(['a', 'b', 'c']): print(i, value)
結果:
0 a 1 b 2 c [Finished in 0.1s]
3、列表生成式
列表生成式即List Comprehensions,是Python內置的非常簡單卻強大的可以用來創建list的生成式。
但如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做?方法一是循環:
\#通過循環生成list L = [] for x in range(1,11): L.append(x*x) print(L) \#通過列表生成式生成list s = [x * x for x in range(1, 11)] print(s)
結果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
寫列表生成式時,把要生成的元素x* x放到前面,后面跟for循環,就可以把list創建出來,十分有用,多寫幾次,很快就可以熟悉這種語法。
還可以使用兩層循環,可以生成全排列:
x = [m + n for m in 'ABC' for n in 'XYZ'] print(x)
結果:
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
列表生成式也可以使用兩個變量來生成list:
d = {'x' : 'A', 'y' : 'B', 'z' : 'C'} y = [k + '=' + v for k,v in d.items()] print(y)
結果:
['x=A', 'y=B', 'z=C']
4、生成器(generator)
在python中,可以一邊循環一邊計算的機制,稱為生成器:generator。
這樣在創建list的時候,可以節省大量的空間。
創建一個generator有很多種方法,第一種方法,只要把列表生成式的[ ]改為( )就可以:
g = (x * x for x in range(10))\#創建生成器 print(g) g1 = next(g)\#獲取生成器的元素 g2 = next(g) print(g1, g2)
結果:
<generator object <genexpr> at 0x000002702100AA40> 0 1 4 9 16 25 36 49 64 81 [Finished in 0.1s]
創建列表生成式和生成器的區別在于,前者是一個list,后者是一個gengrator。
通過next()方法獲取生成器的元素有點麻煩,可以通過for循環迭代生成器。
比如,著名的斐波拉契數列(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' \#fib(10) \#這是輸出斐波那契數列的生成器 def fib_generaor(max): n, a, b = 0, 0, 1 while n < max: yield b#區別在于這點 a, b = b, a+b n = n +1 return 'done' for x in fib_generaor(10): print(x)
結果:
1 1 2 3 5 8 13 21 34 55 [Finished in 0.1s]
仔細觀察,可以看出,fib函數實際上是定義了斐波拉契數列的推算規則,可以從第一個元素開始,推算出后續任意的元素,這種邏輯其實非常類似generator。
也就是說,上面的函數和generator僅一步之遙。要把fib函數變成generator,只需要把print(b)改為yield b就可了。
5、迭代器
我們已經知道,可以直接作用于for循環的數據類型有以下幾種:
一類是集合數據類型,如list、tuple、dict、set、str等;
一類是generator,包括生成器和帶yield的generator function。
這些可以直接作用于for循環的對象統稱為可迭代對象:Iterable。
可以使用isinstance()判斷一個對象是否是Iterable對象。
可以被next()函數調用并不斷返回下一個值的對象稱為迭代器:Iterator。生成器都是Iterator對象,但list、dict、str雖然是Iterable,卻不是Iterator。把list、dict、str等Iterable變成Iterator可以使用iter()函數。