Python高級特性

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異常。