[Python][華為云Python編程創(chuàng)造營][學(xué)習(xí)筆記][12_Python三大神器]
1,迭代器
1.1,迭代
1.1.1,迭代是Python中用于訪問序列結(jié)構(gòu)數(shù)據(jù)的一種方式
- 當(dāng)我們用一個循環(huán)(比如for循環(huán))來遍歷容器(比如列表、元組)中的元素時,這種遍歷的過程就叫迭代。
1.2,可迭代對象
1.2.1,可以被for循環(huán)遍歷的對象成為可迭代對象
- 可迭代對象中需要實(shí)現(xiàn)__iter__或者_(dá)_getitem__方法
1.3,迭代器
1.3.1,迭代器是指遵循迭代器協(xié)議(iterator protocol)的對象
- 迭代器協(xié)議:實(shí)現(xiàn)對象的__iter__和__next__方法,其中__iter__方法返回迭代器對象本身,next()方法返回容器的下一個元素,在沒有后續(xù)元素時拋出StopIteration異常。
- 可迭代對象不是迭代器。
- 使用iter()獲取迭代器對象。
1.3.2,迭代器是一個可以記住遍歷的位置的對象
- 迭代器對象從集合的第一個元素開始訪問(next),直到所有的元素被訪問結(jié)束。迭代器只能往前不能后退。
1.3.3,對于迭代器對象,可以使用next方法獲取
- 當(dāng)元素迭代完后會出現(xiàn)StopIteration異常。
# 字符串,列表或者元組對象都可用于創(chuàng)建迭代器 list = [1,2,3,4] it = iter(list) # 創(chuàng)建迭代器對象 print(next(it)) # 輸出迭代器的下一個元素 1 print(next(it)) # 輸出迭代器的下一個元素 2 # 迭代器對象可以使用常規(guī)for語句進(jìn)行遍歷 list = [1,2,3,4] it = iter(list) # 創(chuàng)建迭代器對象 for x in it: print(x,end=" ") # 1 2 3 4 # 也可以使用next()函數(shù) import sys # 引入sys模塊 list = [1,2,3,4] it = iter(list) # 創(chuàng)建迭代器對象 while True: try: print(next(it),end=" ") # 1 2 3 4 except StopIteration: sys.exit() # 創(chuàng)建一個返回數(shù)字的迭代器,初始值為1,逐步遞增2 class MyNumber: def __iter__(self): self.a = 1 return self def __next__(self): x = self.a self.a += 2 return x myclass = MyNumber() myiter=iter(myclass) print(next(myiter)) # 1 print(next(myiter)) # 3 print(next(myiter)) # 5 print(next(myiter)) # 7 print(next(myiter)) # 9 # 迭代20次后停止執(zhí)行 class MyNumbers: def __iter__(self): self.a = 1 return self def __next__(self): if self.a <= 10: x = self.a self.a += 1 return x else: raise StopIteration myclass = MyNumbers() myiter = iter(myclass) for x in myiter: print(x,end=" ") # 1 2 3 4 5 6 7 8 9 10
2,生成器
2.1,生成器(generator)是一類特殊的迭代器
2.1.1,生成器每次在迭代時可以返回一個或多個值,它可以記錄當(dāng)前狀態(tài)
- 生成器的創(chuàng)建方式:使用yield關(guān)鍵字,使用生成器表達(dá)式(推導(dǎo)式)。
2.2,生成器推導(dǎo)式
2.2.1,推導(dǎo)式形式
G = (x*2 for x in range(5)) print(type(G)) #
2.2.2,判斷是否是生成器
from collections.abc import Generator G = (x*2 for x in range(5)) res = isinstance(G,Generator) print(res) # True
2.3,yield創(chuàng)建生成器
2.3.1,使用yield創(chuàng)建生成器
- 通過yield創(chuàng)建一個產(chǎn)生斐波那契數(shù)列的生成器
import sys def fibonacci(n): # 生成器函數(shù) - 斐波那契數(shù)列 a, b, counter = 0, 1, 0 while True: if (counter > n): return yield a a, b = b, a+b counter += 1 f = fibonacci(10) # f是一個迭代器,由生成器返回生成 while True: try: print(next(f),end=" ") # 0 1 1 2 3 5 8 13 21 34 55 except StopIteration: sys.exit()
2.3.2,為了更好了解yield的工作流程,我們通過Debug來觀察
2.4,生成器取值
2.4.1,生成器可以使用next和send取值
- next,獲取下一個元素。
- send,獲取下一個元素,同時可以向生成器中傳遞一個值。
- next等同于send(None)。
- 第一次取值時,需要使用next或者send(None)。
2.5,執(zhí)行過程(1)
2.5.1,下面例子的執(zhí)行過程
def fib(n): current = 0 num1, num2 = 0, 1 while current < n: num = num1 # 1 num1, num2 = num2, num1+num2 # 2 current += 1 yield num # 3 return 'done' # 6 g = fib(5) # 4 next(g) # 5 # 執(zhí)行過程:-4 -1 -2 -3 -5 -1 -2 ... -6
2.6,執(zhí)行過程(2)
2.6.1,使用yield聲明函數(shù)為生成器
2.6.2,當(dāng)程序執(zhí)行到y(tǒng)ield處時,生成器函數(shù)暫停,等待下一次喚醒(next,send)
- 并且返回當(dāng)前值。
- 和return相似,但是程序暫停而不是結(jié)束。
2.7,關(guān)系
3,裝飾器
裝飾器(Decorators)是修改其他函數(shù)功能的函數(shù)。
3.1,閉包(1)
3.1.1,閉包:是由函數(shù)及其相關(guān)的引用環(huán)境組合而成的實(shí)體。
3.1.2,不同編程語言實(shí)現(xiàn)閉包的方式是不同的,Python中閉包從表現(xiàn)形式上看,如果在一個內(nèi)部函數(shù)里,對在外部作用域(不是在全局作用域)的變量進(jìn)行引用,那么內(nèi)部函數(shù)就被認(rèn)為是閉包。
def func(x): def inner(y): return x+y return inner
3.2,閉包(2)
3.2.1,閉包中不可以直接修改外部函數(shù)的局部變量
- 類似于不能直接在函數(shù)中修改全局變量(可變類型除外),需要使用關(guān)鍵字nonlocal。
3.2.2,閉包的作用
- 當(dāng)閉包執(zhí)行完后,仍然能夠保持住當(dāng)前的運(yùn)行環(huán)境。
- 閉包可以根據(jù)外部作用域的局部變量來得到不同的結(jié)果。
def func1(func): def inner(): print("func1") func() return inner def func2(): print("func2") func1(func2)()
3.3,裝飾器(1)
3.3.1,裝飾器本質(zhì)上是一個Python函數(shù),可以在不改變代碼結(jié)構(gòu)的情況下給代碼添加新的功能。
3.3.2,裝飾器的工作過程:將被裝飾的函數(shù)當(dāng)作參數(shù)傳遞給裝飾器函數(shù)(名稱相同的函數(shù)),并返回裝飾后被裝飾的函數(shù)。
3.3.3,裝飾器是閉包的一種應(yīng)用。
3.3.4,裝飾器的使用
# @裝飾器函數(shù) # def func(): # pass
3.4,裝飾器(2)
3.4.1,裝飾器的作用
def light(func): # 裝飾器函數(shù) print("獲得神光棒x1") def tiga(): func() print("我是光之巨人") return tiga() @light def person(): print("我是某勝利隊隊員大骨") person() # 輸出結(jié)果 # 獲得神光棒x1 # 我是某勝利隊隊員大骨 # 我是光之巨人 # TypeError: 'NoneType' object is not callable def light(func): # 裝飾器函數(shù) print("獲得神光棒x1") def tiga(): func() print("我是光之巨人") return tiga def person(): print("我是某勝利隊隊員大骨") light(person)() # 輸出結(jié)果 # 獲得神光棒x1 # 我是某勝利隊隊員大骨 # 我是光之巨人
3.5,丟失的信息
3.5.1,裝飾器不會改變原有函數(shù)代碼,但是會丟失一部分信息
- 被裝飾函數(shù)的元信息會丟失,如:名字、文檔字符串、注解和參數(shù)簽名
def light(func): # 裝飾器函數(shù) print("獲得神光棒x1") def tiga(): func() print("我是光之巨人") return tiga @light def person(): # 被裝飾的函數(shù) '''我要打怪獸''' print("我是某勝利隊隊員大骨") person() help(person) # 輸出結(jié)果 # 獲得神光棒x1 # 我是某勝利隊隊員大骨 # 我是光之巨人 # Help on function tiga in module __main__: # tiga()
3.6,wraps
3.6.1,為了保留因為使用裝飾器而丟失的信息,可以使用Python中本身提供的裝飾器@wraps來解決
from functools import wraps def light(func): print("獲得神光棒x1") @wraps(func) def tiga(): func() print("我是光之巨人") return tiga @light def person(): '''我想打怪獸''' print("我是某勝利隊隊員大骨") person() help(person) # 輸出結(jié)果 # 獲得神光棒x1 # 我是某勝利隊隊員大骨 # 我是光之巨人 # Help on function person in module __main__: # person() # 我想打怪獸
3.7,被裝飾函數(shù)的參數(shù)
3.7.1,當(dāng)被裝飾函數(shù)擁有參數(shù)時,如何在裝飾器過程中進(jìn)行傳遞?如何構(gòu)建一個通用的裝飾器?
from functools import wraps def func1(func): @wraps(func) def inner(a, b): print("func1") func(a, b) return inner @func1 def func2(a, b): print(a+b) func2(1, 2) # 輸出結(jié)果 # func1 # 3
3.8,帶有參數(shù)的裝飾器
3.8.1,如何通過裝飾器的參數(shù)來控制裝飾器?
- 對當(dāng)前用戶增加權(quán)限:VIP,SVIP,VIP中P
def Decorator(name=None,level="普通會員"): def outer(func): def inner(name): print("歡迎登陸, %s"%level) func(name) return inner return outer @Decorator(level="SVIP") def func(name): print(name) func("張三") # 輸出結(jié)果 # 歡迎登陸, SVIP # 張三
- 通過外部參數(shù),返回一個裝飾器
3.9,裝飾器與類(1)
3.9.1,裝飾器不僅可以是函數(shù),還可以是類(如property)
- 同樣,裝飾器不僅可以修飾函數(shù),還可以修飾類
3.9.2,裝飾器裝飾類
def singleton(cls,*args,**kw): instance={} def _singleton(): if cls not in instance: instance[cls]=cls(*args,**kw) return instance[cls] return _singleton @singleton class Singleton(object): def __init__(self): self.num_sum=0 def add(self): self.num_sum=100
4.0,裝飾器與類(2)
4.0.1,將裝飾器定義為類的形式。
- __call__:魔法方法,可以讓類像方法一樣被調(diào)用。
import time class Wrapper(): def __init__(self,func): self.func=func def __call__(self,*args,**kwargs): start=time.time() result=self.func(*args,**kwargs) end=time.time() print(end-start) return result @Wrapper def func(num): time.sleep(3) return num func(1) # 3.000171422958374
4.1,多個裝飾器
def Tiga(func): print("給我力量吧,Tiga") def tiga(): func() print("獲得Tiga的力量") return tiga def Dyna(func): print("給我力量吧,Dyna") def dyna(): func() print("獲得Dyna的力量") return dyna def Gaia(func): print("給我力量吧,Gaia") def gaia(): func() print("獲得Gaia的力量") return gaia @Tiga @Dyna @Gaia def Z(): print("變身") Z() # 輸出結(jié)果 # 給我力量吧,Gaia # 給我力量吧,Dyna # 給我力量吧,Tiga # 變身 # 獲得Gaia的力量 # 獲得Dyna的力量 # 獲得Tiga的力量
4.2,解除裝飾器
from functools import wraps def light(func): print("獲得神光棒x1") @wraps(func) def tiga(): func() print("我是光之巨人") return tiga @light def person(): print("我是某勝利隊隊員大骨") person() # 輸出結(jié)果 # 獲得神光棒x1 # 我是某勝利隊隊員大骨 # 我是光之巨人 DaGu=person.__wrapped__ DaGu() # 輸出結(jié)果 # 獲得神光棒x1 # 我是某勝利隊隊員大骨
Python
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。