Python高級特性 切片 迭代 列表生成式 生成器java
1、切片python
切片:數據的分段切割。以下定義一個列表而後獲取前五位數據。安全
格式:對象[起始位置:須要讀取的數量:間隔]app
1 >>> olist = list(range(10)) 2 >>> 3 >>> olist 4 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 5 >>> olist[0:5] 6 [0, 1, 2, 3, 4] 7 >>> 8 >>> olist[0:5:2] 9 [0, 2, 4] 10 >>>
定義而且聲明一個olist列表對象,而後經過切片返回一個新的列表對象。其實位置默認是0,而且能夠省略。如olist[:5]。間隔默認是1。函數
range是一個系統函數,返回一個特定的有序的天然數,默認從零開始。測試
1 1 >>> help('range') 2 2 Help on class range in module builtins: 3 3 4 4 class range(object) 5 5 | range(stop) -> range object 6 6 | range(start, stop[, step]) -> range object 7 7 | 8 8 | Return an object that produces a sequence of integers from start (inclusive) 9 9 | to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1. 10 10 | start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3. 11 11 | These are exactly the valid indices for a list of 4 elements. 12 12 | When step is given, it specifies the increment (or decrement). 13 13 |
對於列表而言支持反向讀取,如olist[-1],獲取最後一條數據。那麼對於切片slice而言是否支持???優化
1 >>> olist = list(range(10)) 2 >>> olist[-2: -1] 3 [8] 4 >>> olist[-8: -1] 5 [2, 3, 4, 5, 6, 7, 8] 6 >>> 7 >>> olist[-1] 8 9 9 >>>
從測試結果來看是支持反向切片。可是反向以後切記最後一位角標是-1。ui
之上的測試是對列表List進行的,那麼我接下來看下對於String和tuple是否也適用!!!spa
1 >>> oTuple = (1,2,3,4,5,6) 2 >>> oTuple[0:5:2] 3 (1, 3, 5) 4 >>> 5 >>> 6 >>> str = 'abcdefg' 7 >>> str[0:5:2] 8 'ace' 9 >>>
從執行結果來看和咱們的猜測是徹底一致的。到這裏可能有人會問了那麼既然元組和列表及字符串均可以這麼用,那麼集合set和字典dict那???實際上是不能夠的,由於對於集合和dict而言是沒有下標的。code
1 >>> oset = set([1,2,3]) 2 >>> oset 3 {1, 2, 3} 4 >>> 5 >>> oset[0:2] 6 Traceback (most recent call last): 7 File "<stdin>", line 1, in <module> 8 TypeError: 'set' object is not subscriptable 9 >>> 10 >>> odict = {'a:1','b:2','c:3'} 11 >>> odict[0:2] 12 Traceback (most recent call last): 13 File "<stdin>", line 1, in <module> 14 TypeError: 'set' object is not subscriptable 15 >>>
2、迭代
迭代其實就是對集合<List, Tuple, dict, set等>的遍歷。這裏僅僅是列舉了一些常見的集合,其實這裏只要是Iterable的子類均可以使用迭代器來實現遍歷。判斷以下:
1 >>> oSet = set([1,3,4,5,]) 2 >>> oSet 3 {1, 3, 4, 5} 4 >>> for item in oSet: 5 ... print(item) 6 ... 7 1 8 3 9 4 10 5 11 >>> isinstance(oSet, Iterable) 12 True 13 >>> index = 2 14 >>> 15 >>> isinstance(index, Iterable) 16 False 17 >>>
上述採用的是系統函數isinstance()完成對對象的判斷,判斷給對象是不是Iterable的子類。按照規定只要是Iterable的子類就能夠直接使用for循環實現迭代。
在使用isinstance方法時候判斷是不是Iterable子類的時候,請記住請優先執行導入Iterable操做,默認isinstance方法是在collections類中。故而執行應該在文件頭部增長from collections import Iterable。
這裏重點講解下迭代器如何在迭代中獲取index角標和dict遍歷。
1 >>> olist = ['A','B','C','E'] 2 >>> for index, item in enumerate(olist): 3 ... print(index, ' : ', item) 4 ... 5 0 : A 6 1 : B 7 2 : C 8 3 : E 9 >>>
該出使用的系統方法enumerate(),該方法能夠實現把集合變成角標-元素。
字典集合遍歷方式一獲取key:
1 >>> oDict = {'a:1','b:2','c:3'} 2 >>> 3 >>> oDict 4 {'b:2', 'a:1', 'c:3'} 5 >>> 6 >>> for item in oDict: 7 ... print(item) 8 ... 9 b:2 10 a:1 11 c:3 12 >>>
字典集合遍歷方式二獲取value:
1 >>> oDict = {'a':1,'b':2,'c':3} 2 >>> oDict 3 {'a': 1, 'b': 2, 'c': 3} 4 >>> for value in oDict.values(): 5 ... print(value) 6 ... 7 1 8 2 9 3 10 >>>
字典集合遍歷方式三獲取key-value:
1 >>> oDict = {'a':1,'b':2,'c':3} 2 >>> oDict 3 {'a': 1, 'b': 2, 'c': 3} 4 >>> for k, v in oDict.items(): 5 ... print(k, " = ", v) 6 ... 7 a = 1 8 b = 2 9 c = 3
3、列表生成式
列表生成式:顧名思義就是生成對應的列表。場景如定義一個天然數1-100放入到指定的集合等。使用方式就是使用系統函數range,前邊已經關於這個方法有過說明,這裏就直接跳過。
range僅僅是獲取有序的天然數,假如咱們需求有天發生了變化,如獲取1-100的平分數,而後放到指定集合,當下range就有點尷尬了。不過好在Python爲咱們作了這樣的定製開發。一塊兒走進代碼。
1 >>> oList = list(range(1,5)) 2 >>> oList 3 [1, 2, 3, 4] 4 >>> 5 >>> nList = [x * x for x in range(1,5)] 6 >>> nList 7 [1, 4, 9, 16] 8 >>>
第一行到第四行是獲取天然數1-5存放於指定集合。第五行到第七行是對天然數1-5開平方而後存放於指定集合中。
上述內容細節還能夠進一步優化,加入僅僅保留偶數的平方,那麼咱們能夠這麼幹。
1 >>> nList = [x * x for x in range(1,5) if x % 2 == 0] 2 >>> nList 3 [4, 16] 4 >>>
列表生成式實現排列組合,666。。。<又名for循環嵌套>
1 >>> nList = [m + n for m in 'ADC' for n in 'MVP'] 2 >>> nList 3 ['AM', 'AV', 'AP', 'DM', 'DV', 'DP', 'CM', 'CV', 'CP'] 4 >>>
這裏其實就是嵌套for循環。如何不理解能夠換個方式去看。
1 >>> nList = [] 2 >>> for m in 'ADC': 3 ... for n in 'MVP': 4 ... nList.append(m + n) 5 ... 6 >>> nList 7 ['AM', 'AV', 'AP', 'DM', 'DV', 'DP', 'CM', 'CV', 'CP'] 8 >>>
看着這些代碼是否是更好理解怎麼肥事。
4、生成器<Generator>
生成器能夠理解爲對生成器的優化,這裏優化主要是說在內存上的優化。舉例子來講,假如須要數據有序的天然數零到一萬存放於列表中,這時能夠有兩種方式,一是直接生成一刀一萬的天然數放到內存中。另外一種是用到那個就讀那個到內存中。很顯然第二種方式在內存這塊要優於第一種,這就是咱們要說的生成器。
生成器聲明格式和列表生成式大體相同,區別在於外圍中括號和括號去別。看下生成器在代碼中的使用,以及數據獲取、
1 >>> oGenerator = (n for n in range(1, 5)) 2 >>> oGenerator 3 <generator object <genexpr> at 0x0000000002D60BF8> 4 >>> next(oGenerator) 5 1 6 >>> next(oGenerator) 7 2 8 >>> next(oGenerator) 9 3 10 >>> next(oGenerator) 11 4 12 >>> next(oGenerator) 13 Traceback (most recent call last): 14 File "<stdin>", line 1, in <module> 15 StopIteration 16 >>>
第一行建立了一個生成器對象。直接該對象。返回了個這'<generator object <genexpr> at 0x0000000002D60BF8>',What???一臉懵逼。。。好吧暫且把它看作是python對一個對象的表達形式吧,就如同java中對象打印同樣,得到是對應的hashcode值。
next()讀取生成器中的數據的系統方法。該方法獲取生成器中的數據遇到yield則執行數據返回。yield的功能等同於return,不一樣點在於yield掛機程序執行,並不會結束方法執行。
這裏對於方法next()使用不是絕對安全的,在地十二行處調用next()方法拋出了一個StopIteration異常,意思就是已是最後一個數據了,沒有更多數據了。那麼怎麼避免這個問題那???也許有些人想到了for循環,那麼對於這個generator是否也適用???咱們有咱們的辦法,isinstance()。想到了就去作。
1 >>> isinstance(oGenerator, Iterable) 2 True 3 >>>
如上代碼證實了Generator生成器其實也是Iterable的子類,那麼這就簡單了。
>>> oGenerator = (n for n in range(1, 5)) >>> for item in oGenerator: ... print(item) ... 1 2 3 4 >>>
到了這裏咱們也就發現了正確的讀取生成器Generator中數據的方法。
下一步就是如何自定義生成器????
1 >>> def step(): 2 ... print('step 1') 3 ... yield 1 4 ... print('step 2') 5 ... yield 6 6 ... print('step 3') 7 ... yield 12 8 ... 9 >>> 10 >>> g = step() 11 >>> g 12 <generator object step at 0x00000000024D2EB8> 13 >>> next(g) 14 step 1 15 1 16 >>> next(g) 17 step 2 18 6 19 >>> next(g) 20 step 3 21 12 22 >>>
自定義Generator適用關鍵字yield,方法在執行next()過程當中,每當遇到yield都會直接返回,可是方法並未真正結束,僅僅是暫停。當你再一次調用next()則會在當前暫停出繼續執行,知道執行徹底結束,最後拋出StopIteration異常。
這裏演示過程當中採用了next()方法遍歷自定義的Generator,在真正使用過程當中儘可能使用for循環,由於for內部會處理StopIteration異常。