切片
切片就是用于截取集合雇庙,字符串的工具。下面是如何使用:
Ls = list(range(100))
# 取前面2個元素灶伊,如果是0 可以省略不寫
print(Ls[:2])
# 取倒數(shù)第一個到倒數(shù)第三個元素
print(Ls[-3:])
# 前10個數(shù)疆前,每兩個取一個
print(Ls[:10:2])
# 所有數(shù),每5個取一個
print(Ls[::5])
# 只寫[:]就可以原樣復(fù)制一個list
print(Ls[:])
Tp = (0, 1, 2, 3, 4, 5, 6, 7)
# 使用切片后獲取的還是一個tuple
tp_ = Tp[:3]
print(tp_)
str = "ABCDEFG"
# 切片也可以截取字符串,截取之后仍然是字符串
print(str[:3])
迭代
我們都知道聘萨,可以使用 for in這個循環(huán)來遍歷集合竹椒,字典,字符串等等匈挖,這種遍歷就叫做迭代碾牌,那么如何判斷一個對象是否可以被迭代?可以寫如下代碼儡循,使用Iterable來判斷:
from collections import Iterable
s = "123456"
if isinstance(s,Iterable):
for ch in s:
print(ch)
那么如果要對list實(shí)現(xiàn)類似Java那樣的下標(biāo)循環(huán)怎么辦?Python內(nèi)置的enumerate函數(shù)可以把一個list變成索引-元素對征冷,這樣就可以在for循環(huán)中同時迭代索引和元素本身:
l = list(range(20))
for i,value in enumerate(l):
print(i,", ",value)
那么問問择膝,以下程序執(zhí)行結(jié)果是什么?
for x, y in [(3, 1), (2, 4), (3, 9)]:
print(x, y)
for x, y, z in [(3, 1, 3), (2, 4, 3), (3, 9, 3)]:
print(x, y, z)
# 比如dict的items()可以同時迭代key和value
for k, v in d.items():
print(k, '=', v)
for循環(huán)其實(shí)可以同時使用兩個甚至多個變量
列表生成式
列表生成式就是簡化生成指定格式列表的一種表達(dá)式检激,舉個例子肴捉,我們要生成1到n之間數(shù)的nn的列表,這個時候叔收,通常需要定義一個1到n的集合齿穗,然后在循環(huán)這個集合,計算nn的再裝入一個集合饺律。這樣比較麻煩窃页,而列表生成式把要生成的元素x * x放到前面,后面跟for循環(huán),就可以把list創(chuàng)建出來:
# 計算1-10之間元素的平方
print([a * a for a in list(range(1, 10))])
# 加入if判斷脖卖,篩選出偶數(shù)的平方
print([a * a for a in list(range(1, 10)) if a % 2 == 0])
# 使用兩層循環(huán)乒省,可以生成全排列,當(dāng)然 也可以兩層以上的循環(huán)
print([m + n for m in 'ABC' for n in 'XYZ'])
# 也可以使用兩個變量來生成list:
d = {'x': 'A', 'y': 'B', 'z': 'C' }
print([k + '=' + v for k, v in d.items()])
生成器
上面的列表生成式我們是生成了10的集合列表,加入我們需要生成一個1000萬的集合畦木?但是一般我們只需要訪問其中前面幾個元素袖扛,后面的只是在特殊情況下面才用到,這個時候就有兩個問題了十籍,第一:需要大量的內(nèi)存蛆封,第二:浪費(fèi)大量內(nèi)存。我們希望生成的這個集合只是在需要的時候產(chǎn)出元素勾栗,所以娶吞,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環(huán)的過程中不斷推算出后續(xù)的元素械姻,這樣就不會出現(xiàn)上面兩個問題了妒蛇。那么在Python中,這種一邊循環(huán)一邊計算的機(jī)制楷拳,稱為生成器:generator绣夺。
- 第一種創(chuàng)建generator的方式:只要把一個列表生成式的[]改成(),就創(chuàng)建了一個generator
# 創(chuàng)建一個generator
l = (x * x for x in list(range(10)))
print(l)
# 通過next()函數(shù)獲得generator的下一個返回值,generator保存的是算法欢揖,每次調(diào)用next(g)陶耍,
# 就計算出g的下一個元素的值,直到計算到最后一個元素她混,沒有更多的元素時烈钞,拋出StopIteration的錯誤。
# 這里坤按,generator也是可迭代對象毯欣,我們創(chuàng)建了一個generator后,基本上永遠(yuǎn)不會調(diào)用next()臭脓,而是通過for
# 循環(huán)來迭代它酗钞,并且不需要關(guān)心StopIteration的錯誤
for n in l:
print(n)
- 第二種創(chuàng)建generator方式:如果一個函數(shù)定義中包含yield關(guān)鍵字,那么這個函數(shù)就不再是一個普通函數(shù)来累,而是一個generator
# 實(shí)現(xiàn)一個斐波拉契數(shù)列砚作,fib函數(shù)實(shí)際上是定義了斐波拉契數(shù)列的推算規(guī)則,可以從第一個元素開始嘹锁,
# 推算出后續(xù)任意的元素葫录,這種邏輯其實(shí)非常類似generator
def fib(max):
n, a, b = 0, 0, 1
while n < max:
# 加上下面代碼,這個就不是函數(shù)而是一個generator,在執(zhí)行過程中领猾,遇到y(tǒng)ield就中斷米同,下次又繼續(xù)執(zhí)行骇扇。
yield b
# t = (b, a + b) # t是一個tuple
# a = t[0]
# b = t[1]
a, b = b, a + b
n = n + 1
return 0
# 直接獲取數(shù)列,為了不報StopIteration錯誤窍霞,一般都用for來遍歷匠题,不會用next函數(shù)
for x in fib(6):
print(x)
# 如果需要拿到fib生成的return值,可以這么寫:
f = fib(6)
while True:
try:
print(next(f))
except StopIteration as e: # 捕捉這個異常就可以獲取了
print(e.value)
break
Iterable與Iterator區(qū)別
Iterable:凡是可作用于for循環(huán)的對象都是Iterable類型但金,如list韭山、tuple、dict冷溃、set钱磅、str等,可以使用isinstance()判斷一個對象是否是Iterable對象
Iterator: 凡是可作用于next()函數(shù)的對象都是Iterator類型似枕,它們表示一個惰性計算的序列盖淡,生成器都是Iterator對象,但list凿歼、dict褪迟、str雖然是Iterable,卻不是Iterator答憔。因?yàn)镻ython的Iterator對象表示的是一個數(shù)據(jù)流味赃,Iterator對象可以被next()函數(shù)調(diào)用并不斷返回下一個數(shù)據(jù),直到?jīng)]有數(shù)據(jù)時拋出StopIteration錯誤虐拓⌒乃祝可以把這個數(shù)據(jù)流看做是一個有序序列,但我們卻不能提前知道序列的長度蓉驹,只能不斷通過next()函數(shù)實(shí)現(xiàn)按需計算下一個數(shù)據(jù)城榛,所以Iterator的計算是惰性的,只有在需要返回下一個數(shù)據(jù)時它才會計算态兴。Iterator甚至可以表示一個無限大的數(shù)據(jù)流狠持,例如全體自然數(shù)。而使用list是永遠(yuǎn)不可能存儲全體自然數(shù)的诗茎。
把list工坊、dict、str等Iterable變成Iterator可以使用iter()函數(shù):
print( isinstance(iter('abc'), Iterator))