Python高級特性

1. 切片

對經常取指定索引範圍的操作,用循環十分繁瑣,因此,Python提供了切片(Slice)操作符,能大大簡化這種操作。

L[0:3]表示,從索引0開始取,直到索引3爲止,但不包括索引3。即索引012,正好是3個元素

如果第一個索引是0,還可以省略

類似的,既然Python支持L[-1]取倒數第一個元素,那麼它同樣支持倒數切片

>>> L= ['Alice','Bob','Clilly','Donna','Frank']
>>> L[0:3]
['Alice', 'Bob', 'Clilly']
>>> L[:3]
['Alice', 'Bob', 'Clilly']
>>> L[1:3]
['Bob', 'Clilly']
>>> L[-2:]
['Donna', 'Frank']
>>>

什麼都不寫就是複製了一個list

tuple也是一種list,唯一區別是tuple不可變。因此,tuple也可以用切片操作,只是操作的結果仍是tuple

字符串'xxx'也可以看成是一種list,每個元素就是一個字符。因此,字符串也可以用切片操作,只是操作結果仍是字符串:

Practice: 利用切片操作,實現一個trim()函數,去除字符串首尾空格

>>> def trim(s):
 while s[:1]==" ":
  s=s[1:]
 while s[-1:]==" ":
  s=s[:-1]
 return s

>>> trim(' hello  ')
'hello'
>>> trim('joke   ')
'joke'
>>>

2.迭代

如果給定一個list或tuple,我們可以通過for循環來遍歷這個list或tuple,這種遍歷我們稱之爲迭代(Iteration)

在Python中,迭代式通過for ...in 來完成的

>>> d = {'a':1, 'b':2, 'c':3}
>>> for key in d:
 print(key)

 
a
b
c

默認情況下,dict迭代的是key,如果要迭代value,可以用 for value in d.values()

如果要同時迭代key和value,可以用for k, v in d.items()

>>> for key,value in d.items():
 print(key, value)

 
a 1
b 2
c 3
>>>

字符串也是可迭代對象,因此,也可以作爲for循環:

>>> for ch in 'ABC':
 print(ch)

 
A
B
C
>>>

所以,當我們使用for循環時,只要作用於一個可迭代對象,for循環就可以正常運行,而我們不太關心該對象究竟是list還是其他數據類型。

可以通過collections模塊的iterable類型判斷:

>>> from collections import Iterable
>>> isinstance('abc', Iterable)
True
>>> isinstance([1,2,3], Iterable)
True
>>> isinstance(123, Iterable)
False
>>>

如果要對list實現類似Java那樣的下標循環怎麼辦?Python內置的enumerate函數可以把一個list變成索引-元素對,這樣就可以在for循環中同時迭代索引和元素本身:

>>> for i, value in enumerate(['A', 'B', 'C']):
 print(i, value)

 
0 A
1 B
2 C
>>>

同時引用兩個變量,在Python裏也是很常見的:

>>> for x, y in [(1,1), (2,4), (3,9)]:
 print(x,y)

 
1 1
2 4
3 9
>>>

Practice: 使用迭代查找list中的最大值和最小值,並返回一個tuple:

>>> def findMinAndMax(L):
 if len(L)==0:
  return(None, None)
 else:
  max = L[0]
  min = L[0]
 for s in L:
  if s>max:
   max =s
  if s<min:
   min=s
 return(min,max)

>>> findMinAndMax([8,0,9,7])
(0, 9)
>>> findMinAndMax([])
(None, None)
>>> findMinAndMax([9])
(9, 9)
>>>

3. 列表生成式

要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用list(range(1, 11))

>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

生成[1x1, 2x2, 3x3, ..., 10x10]怎麼做

>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

篩選出僅偶數的平方

>>> [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']

列出當前目錄下的所有文件和目錄名,可以通過一行代碼實現

>>> import os
>>> [d for d in os.listdir('.')]
['df.py', 'DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'ls.py', 'NEWS.txt', 'python.exe', 'python3.dll', 'python36.dll', 'pythonw.exe', 'Scripts', 'tcl', 'Tools', 'vcruntime140.dll']
>>> for 循環

可以同時使用來兩個甚至多個變量,比如dict的items()

4. 生成器

在Python中一邊循環一邊計算的機制稱爲生成器:generator

>>> g =(x*x for x in range(10))
>>> for n in g:
 print(n)

 
0
1
4
9
16
25
36
49
64
81
>>>

斐波那契數列:

函數實現:

>>> 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(6)
1
1
2
3
5
8
'done'
>>>

生成器實現:

>>> def fib(max):
 n,a,b =0,0,1
 while n<max:
  yield b
  a,b=b,a+b
  n=n+1
 return 'done'

>>> for n in fib(6):
 print(n)

 
1
1
2
3
5
8
>>>

generator是非常強大的工具,在Python中可以簡單地把列表生成式改成generator,也可以通過函數實現複雜邏輯的generator。

要理解generator的工作原理,它是在for循環的過程中不斷計算出下一個元素,並在適當的條件結束for循環。對於函數改成generator來說,遇到return語句或者執行到函數體最後一行語句,就是結束generator的指令,for循環隨之結束。

區分普通函數和generator、函數,普通函數直接返回結果,generator函數的“調用”實際返回一個generator對象:

>>> r = abs(6)
>>> r
6
>>> g = fib(6)
>>> g
<generator object fib at 0x06042ED0>
>>>

Practice:用generator輸出楊輝三角:

          1
         / \
        1   1
       / \ / \
      1   2   1
     / \ / \ / \
    1   3   3   1
   / \ / \ / \ / \
  1   4   6   4   1
/ \ / \ / \ / \ / \
1   5   10  10  5   1

>>> def triangles():
 n=0
 L=[1]
 while n<10:
  yield L
  L = [1]+[L[i]+L[i+1] for i in range(n)]+[1]
  n=n+1

>>> for i in triangles():
 print(i)

 
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
>>>

5. 迭代器

我們已經知道,可以直接作用於for循環的數據類型有以下幾種:

一類是集合數據類型,如listtupledictsetstr等;

一類是generator,包括生成器和帶yield的generator function。

這些可以直接作用於for循環的對象統稱爲可迭代對象:Iterable

可以使用isinstance()判斷一個對象是否是Iterable對象:

而生成器不但可以作用於for循環,還可以被next()函數不斷調用並返回下一個值,直到最後拋出StopIteration錯誤表示無法繼續返回下一個值了。

可以被next()函數調用並不斷返回下一個值的對象稱爲迭代器:Iterator

小結:

凡是可作用於for循環的對象都是Iterable類型;

凡是可作用於next()函數的對象都是Iterator類型,它們表示一個惰性計算的序列;

集合數據類型如listdictstr等是Iterable但不是Iterator,不過可以通過iter()函數獲得一個Iterator對象。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章