Python三大器

迭代器、生成器、裝飾器python

1、裝飾器算法

1、函數對象:能夠把函數名(不帶括號)當成變量去用,關聯的值是該函數的內存地址閉包

2、閉包函數=做用域+函數嵌套+函數對象app

  核心點:內部函數傳參的關係查找是以定義階段爲準函數

3、什麼是閉包函數?工具

  閉包是一個嵌套函數,內層函數調用了外層函數做用域的變量,外層函數返回值爲內層函數名spa

  實質:爲函數wrapper傳參的一種方式翻譯

  「函數指的是該函數是內嵌函數code

  「函數指的是該函數包含對其外層函數做用域名字的引用orm

def outer():
    x=1
    def wrapper():
        print(x)
    return wrapper
f=outer()  #爲何要返回函數名wrapper:打破內嵌函數wapper只能在outer函數內部調用的規則,使得重回全局調用
f()

4、閉包函數解決的痛點:當wrapper函數體須要傳參,又不能直接經過形參傳入時,閉包就能夠解決此問題

5、什麼是裝飾器?

  定義一個函數(類),在不改變被裝飾函數源代碼及調用方式的狀況下爲其增長功能。

import time
def target(x,y): time.sleep(3) print("my name is {} ,age is {}".format(x,y)) return "ok"
#需求:不改變target函數源代碼和調用方式的狀況下統計target函數的運行時間 import time
def outer(func): #func體現閉包的功能,給wrapper函數體傳入須要的參數func,爲了避免改變target源碼 def wrapper(*args,**kwargs): #*args,**kwargs被裝飾函數須要的參數 start=time.time() res=func(*args,**kwargs) end=time.time() print(end-start) return res return wrapper #target=outer(target) #爲了避免改變target調用方式 #偷樑換柱:將target函數名指向的內存地址換成了wrapper @outer def target(x,y): time.sleep(3) print("my name is {} ,age is {}".format(x,y)) return "ok" target("lennie",28)#沒動源碼,也沒改變調用方式

6、無參裝飾器模板

def outer(func):
    def wrapper(*args,**kwargs):
        
        res=func(*args,**kwargs)
        
        return res
    return wrapper    

7、有參裝飾器

  在outer函數外再套一層函數outer2,將outer函數體須要的參數,經過outer2形參傳入,即成了有參裝飾器。

 

2、迭代器

1、迭代:每一次對過程的重複稱爲一次迭代,而與單純的重複不一樣,每一次迭代獲得的結果會做爲下一次迭代的初始值

#重複
while True:
    msg = input('>>: ').strip()
    print(msg)
    
#迭代    
goods=['mac','lenovo','acer','dell','sony']
index=0
while index < len(goods):
    print(goods[index])
    index+=1

2、可迭代對象:內置有__iter__()方法的對象都是可迭代對象,字符串、列表、元組、字典、集合、打開的文件都是可迭代對象,能夠直接被for循環遍歷經過obj.__iter__()或者iter(obj)能夠返回一個迭代器對象iterator

3、迭代器:迭代器即用來迭代取值的工具Python提供的一種統一的、不依賴於索引的迭代取值方式,只要存在多個,不管序列類型仍是非序列類型均可以按照迭代器的方式取值。

四、迭代器對象:內置有__next__()方法的對象,能夠經過iterator.__next__()或者next(iterator)取出出迭代器中的下一個值,能夠直接被for循環遍歷

>>> s={1,2,3} # 可迭代對象s
>>> i=iter(s)  # 本質就是在調用s.__iter__(),返回s的迭代器對象i,
>>> next(i) # 本質就是在調用i.__next__()
1
>>> next(i)
2
>>> next(i)
3
>>> next(i)  #拋出StopIteration的異常,表明無值可取,迭代結束

  

2、生成器

一、什麼是生成器/生成器對象?

  生成器函數(含yield關鍵字)的返回值爲生成器對象,內置有__iter__()和__next__()方法,因此生成器自己就是一個迭代器能夠直接被for循環遍歷

>>> def my_range(start,stop,step=1):
...     print('start...')
...     while start < stop:
...         yield start
...         start+=step
...     print('end...')
... 
>>> g=my_range(0,3)
>>> g
<generator object my_range at 0x104105678> #直接調用不執行函數體
>>> g.__iter__
<method-wrapper '__iter__' of generator object at 0x1037d2af0>
>>> g.__next__
<method-wrapper '__next__' of generator object at 0x1037d2af0>
>>> next(g) # 觸發函數執行直到遇到yield則中止,將yield後的值返回,並在當前位置掛起函數
start...
0
>>> next(g) # 再次調用next(g),函數從上次暫停的位置繼續執行,直到從新遇到yield...
1
>>> next(g) # 周而復始...
2
>>> next(g) # 觸發函數執行沒有遇到yield則無值返回,即取值完畢拋出異常結束迭代
end...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

二、什麼是生成器函數: 

  1. 含有yield語句的函數
  2. 調用生成器函數將返回一個生成器對象,不執行函數體
  3. yield翻譯爲產生生成」,返回多個對象用yield(迭代),返回一個對象用return

(1) 調用生成器函數會自動建立迭代器對象。

(2) 調用迭代器對象的__next__()方法時才執行生成器函數。

(3) 每次執行到yield語句時返回數據,暫時離開。

(4) 待下次調用__next__()方法時繼續從離開處繼續執行。

三、做用:在循環過程當中,按照某種算法推算數據,沒必要建立容器存儲完整的結果,從而節省內存空間。數據量越大,優點越明顯。

四、生成器表達式

  建立一個生成器對象有兩種方式,一種是調用帶yield關鍵字的函數,另外一種就是生成器表達式,與列表生成式的語法格式相同,只須要將[]換成(),即:

>>> [x*x for x in range(3)]
[0, 1, 4]
>>> g=(x*x for x in range(3))
>>> g
<generator object <genexpr> at 0x101be0ba0>
>>> next(g)    #對比列表生成式,生成器表達式的優勢天然是節省內存(一次只產生一個值在內存中)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g) #拋出異常StopIteration
相關文章
相關標籤/搜索