Python的代碼不是越復(fù)雜越好予权,而是越簡(jiǎn)單越好,開發(fā)效率越簡(jiǎn)單越高
切片
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
[L[0], L[1], L[2]]
另一種方法
L[0:3]
L[0:3]表示另伍,從索引0開始取,直到索引3為止绞旅,但不包括索引3摆尝。即索引0,1因悲,2堕汞,正好是3個(gè)元素。
如果第一個(gè)索引是0晃琳,還可以省略:
L[:3]
- 負(fù)數(shù)的情況
L[-2:-1]
tuple也是一種list讯检,唯一區(qū)別是tuple不可變。因此蝎土,
tuple也可以用切片操作视哑,只是操作的結(jié)果仍是tuple字符串'xxx'也可以看成是一種list,每個(gè)元素就是一個(gè)字符誊涯。因此挡毅,字符串也可以用切片操作,只是操作結(jié)果仍是字符串
總結(jié):有了切片操作暴构,很多地方循環(huán)就不再需要了跪呈。Python的切片非常靈活,一行代碼就可以實(shí)現(xiàn)很多行循環(huán)才能完成的操作取逾。
迭代
在Python中耗绿,迭代是通過for ... in來完成的
Python的for循環(huán)抽象程度要高于Java的for循環(huán),因?yàn)镻ython的for循環(huán)不僅可以用在list或tuple上砾隅,還可以作用在其他可迭代對(duì)象上
Python內(nèi)置的一種數(shù)據(jù)類型是列表:list误阻。list是一種有序的集合,可以隨時(shí)添加和刪除其中的元素。
默認(rèn)情況下究反,dict迭代的是key寻定。如果要迭代value,可以用for value in d.values()精耐,如果要同時(shí)迭代key和value狼速,可以用for k, v in d.items()
d = {'a': 1, 'b': 2, 'c': 3}
for key in d:
print(key)
- 由于字符串也是可迭代對(duì)象,因此卦停,也可以作用于for循環(huán)
for ch in 'ABC':
print(ch)
- 如何判斷一個(gè)對(duì)象是可迭代對(duì)象呢向胡?方法是通過collections模塊的Iterable類型判斷
from collections import Iterable
isinstance('abc', Iterable) # str是否可迭代
- Python內(nèi)置的enumerate函數(shù)可以把一個(gè)list變成索引-元素對(duì),這樣就可以在for循環(huán)中同時(shí)迭代索引和元素本身
for i, value in enumerate(['A', 'B', 'C']):
print(i, value)
列表生成式
[x * x for x in range(1, 11)]
[x * x for x in range(1, 11) if x % 2 == 0]
[m + n for m in 'ABC' for n in 'XYZ']
用兩個(gè)for實(shí)現(xiàn)全排列
- for循環(huán)其實(shí)可以同時(shí)使用兩個(gè)甚至多個(gè)變量惊完,比如dict的items()可以同時(shí)迭代key和value
d = {'x': 'A', 'y': 'B', 'z': 'C' }
for k, v in d.items():
print(k, '=', v)
生成器
受到內(nèi)存限制僵芹,列表容量肯定是有限的。而且专执,創(chuàng)建一個(gè)包含100萬(wàn)個(gè)元素的列表淮捆,不僅占用很大的存儲(chǔ)空間,如果我們僅僅需要訪問前面幾個(gè)元素本股,那后面絕大多數(shù)元素占用的空間都白白浪費(fèi)了
一邊循環(huán)一邊計(jì)算的機(jī)制,稱為生成器:generator
創(chuàng)建generator
- 只要把一個(gè)列表生成式的[]改成()桐腌,就創(chuàng)建了一個(gè)generator
g = (x * x for x in range(10))
- 如果要一個(gè)一個(gè)打印出來拄显,可以通過next()函數(shù)獲得generator的下一個(gè)返回值
next(g)
- 使用for循環(huán),因?yàn)間enerator也是可迭代對(duì)象
g = (x * x for x in range(10))
for n in g:
print(n)
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的另一種方法案站。如果一個(gè)函數(shù)定義中包含yield關(guān)鍵字躬审,那么這個(gè)函數(shù)就不再是一個(gè)普通函數(shù),而是一個(gè)generator
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和函數(shù)的執(zhí)行流程不一樣蟆盐。函數(shù)是順序執(zhí)行承边,遇到return語(yǔ)句或者最后一行函數(shù)語(yǔ)句就返回。而變成generator的函數(shù)石挂,在每次調(diào)用next()的時(shí)候執(zhí)行博助,遇到y(tǒng)ield語(yǔ)句返回,再次執(zhí)行時(shí)從上次返回的yield語(yǔ)句處繼續(xù)執(zhí)行
def odd():
print('step 1')
yield 1
print('step 2')
yield(3)
print('step 3')
yield(5)
o = odd()
next(o)
- 同樣的痹愚,把函數(shù)改成generator后富岳,我們基本上從來不會(huì)用next()來獲取下一個(gè)返回值,而是直接使用for循環(huán)來迭代
迭代器
- 可以直接作用于for循環(huán)的數(shù)據(jù)類型有以下幾種:
一類是集合數(shù)據(jù)類型拯腮,如list窖式、tuple、dict动壤、set萝喘、str等;
一類是generator,包括生成器和帶yield的generator function阁簸。
這些可以直接作用于for循環(huán)的對(duì)象統(tǒng)稱為可迭代對(duì)象:Iterable弦蹂。
可以使用isinstance()判斷一個(gè)對(duì)象是否是Iterable對(duì)象
from collections import Iterable
isinstance([], Iterable)
- 可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)值的對(duì)象稱為迭代器:Iterator。
可以使用isinstance()判斷一個(gè)對(duì)象是否是Iterator對(duì)象:
from collections import Iterator
isinstance((x for x in range(10)), Iterator)
isinstance([], Iterator)
- 生成器都是Iterator對(duì)象强窖,但list凸椿、dict、str雖然是Iterable翅溺,卻不是Iterator脑漫。
把list、dict咙崎、str等Iterable變成Iterator可以使用iter()函數(shù):
isinstance(iter([]), Iterator)
- 這是因?yàn)镻ython的Iterator對(duì)象表示的是一個(gè)數(shù)據(jù)流优幸,Iterator對(duì)象可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)數(shù)據(jù),直到?jīng)]有數(shù)據(jù)時(shí)拋出StopIteration錯(cuò)誤褪猛⊥耍可以把這個(gè)數(shù)據(jù)流看做是一個(gè)有序序列,但我們卻不能提前知道序列的長(zhǎng)度伊滋,只能不斷通過next()函數(shù)實(shí)現(xiàn)按需計(jì)算下一個(gè)數(shù)據(jù)碳却,所以Iterator的計(jì)算是惰性的,只有在需要返回下一個(gè)數(shù)據(jù)時(shí)它才會(huì)計(jì)算笑旺。
Iterator甚至可以表示一個(gè)無限大的數(shù)據(jù)流昼浦,例如全體自然數(shù)。而使用list是永遠(yuǎn)不可能存儲(chǔ)全體自然數(shù)的筒主。