1.閉包回顧html
在學習裝飾器以前,能夠先複習一下什麼是閉包?
在嵌套函數內部的函數可使用外部變量(非全局變量)叫作閉包!
def wrapper(): money =10 def inner(num): nonlocal money money +=num print(money) print(inner.__closure__) #不返回none的話就是閉包 return inner wrapper()(100)
裝飾器的本質就是閉包
2.裝飾器python
裝飾器本質上就是一個python函數,他可讓其餘函數在不須要作任何代碼變更的前提下,增長額外的功能,裝飾器的返回值也是一個函數對象。
裝飾器的應用場景:好比插入日誌,性能測試,事務處理,緩存等等場景。
#簡單的裝飾器 def func(): print('嘻嘻更健康') def timmer(f): def inner(): start_time = time.time() time.sleep(0.1) f() end_time = time.time() print('----> 執行效率%s' % (end_time - start_time)) return inner func = timmer(func) # inner func() # inner()
這是最簡單的裝飾器,裝飾任何函數,只須要加一句func = timmer(func)
3.裝飾器語法糖緩存
import time def timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner @timer 等價於func1 = timer(func1),@timer會先拿到下面函數的名字,而後把拿到名字的函數傳給timer裝飾器函數 def func1(): print('in func1') func1()
def timer(func): def inner(a): start = time.time() func(a) print(time.time() - start) return inner @timer def func1(a): print(a) func1(1)
import time def timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner @timer #==> func1 = timer(func1) def func1(a,b): print('in func1') @timer #==> func2 = timer(func2) def func2(a): print('in func2 and get a:%s'%(a)) return 'fun2 over' func1('aaaaaa','bbbbbb') print(func2('aaaaaa'))
上面的裝飾器已經很是完美了,可是有咱們正常狀況下查看函數信息的方法在此處都會失效:閉包
from functools import wraps def deco(func): @wraps(func) #加在最內層函數正上方,顯示被裝飾的函數 def wrapper(*args,**kwargs): return func(*args,**kwargs) return wrapper @deco def index(): '''哈哈哈哈''' print('from index') print(index.__doc__) #顯示被裝飾函數的註釋 print(index.__name__) #顯示被裝飾的函數名
4.開放封閉原則app
開放對擴展代碼--->新添加的功能 封閉修改源代碼--->不要修改源代碼 改變了人家調用方式---->不能改變其原有的調用方式
5.帶參數的裝飾器ide
假如你有成千上萬個函數使用了一個裝飾器,如今你想把這些裝飾器都取消掉,你要怎麼作? 一個一個的取消掉? 沒日沒夜忙活3天。。。 過兩天你領導想通了,再讓你加上。。。 def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''執行函數以前要作的''') re = func(*args,**kwargs) if flag: print('''執行函數以後要作的''') return re return inner return timer @outer(False) def func(): print(111) func()
6.多個裝飾器裝飾一個函數函數
def wrapper1(func): def inner(): print('wrapper1 ,before func') func() print('wrapper1 ,after func') print('wrapper1.inner',id(inner)) return inner def wrapper2(func): def inner(): print('wrapper2 ,before func') func() print('func',id(func)) print('wrapper2 ,after func') print('wrapper2.inner',id(inner)) return inner @wrapper2 # wrapper1.inner = wrapper2(wrapper1.inner) == wrapper2.inner @wrapper1 # f = wrapper1(f)===>f =wrapper1.inner def f(): print('in f') f() print(id(f)) #裝飾器是函數最上面的裝飾器開始調用,可是執行是從上面的裝飾器開始執行的 #嵌套裝飾器的返回值,返回給上一層 wrapper2 ,before func wrapper1 ,before func in f wrapper1 ,after func wrapper1.inner 189913016 func 189913016 wrapper2 ,after func wrapper2.inner 189913560 189913560
多層嵌套裝飾器的返回值(函數對象),返回給上一層,意義是:給裝飾器在加上一個裝飾器
7.裝飾器執行流程及原理,做用post
裝飾器的組成:
1.閉包 2.語法糖
裝飾器的做用:
1.裝飾器本質上是一個高級Python函數,經過給別的函數添加@標識的形式實現對函數的裝飾
2.它可讓其餘函數在不須要作任何代碼變更的前提下增長額外功能,裝飾器的返回值也是一個函數對象。它常常用於有切面需求的場景,好比:插入日誌、性能測試、事務處理、緩存、權限校驗等場景。
裝飾器是解決這類問題的絕佳設計,有了裝飾器,咱們就能夠抽離出大量與函數功能自己無關的雷同代碼並繼續重用。
裝飾器的原理:就是利用閉包函數來實現,閉包函數的原理就是包含內層函數的return和外層環境變量
8.高級內置函數性能
***#高級函數默認已經幫咱們作了一次for循環的過程**** lambda: 是匿名函數,不須要定義,直接調用,能夠配合其餘高級函數一塊兒使用 lambda x:x>3 第一個是參數,第二個是返回值(能夠作filter的過濾條件) sorted: 排序,sorted([1,3,4,2,7,6]) 默認是升序排序,加上reverse=True是降序, sorted(li,key=func)能夠有兩個參數,第一個參數必須是可迭代對象,第二個參數key是指定的排序規則,能夠是函數,也能夠是表達式 sorted配合lambda li =['你好啦啦啦啦','我很好','你們都好'] print(sorted(li,key=lambda x:len(x))) filter: 是過濾函數,filter(func,li),第一個參數是一個函數的內存地址,第二個參數是可迭代對象,和sorted正好相反 filter配合lambda li = [1,3,6,2,5,4,8,11,23,45,14] #排除小於5的並排序 print(sorted(filter(lambda x:x>5,li)))# 既然是過濾函數,就得有過濾條件,正好lambda的第二個參數是返回值,就能夠以其爲過濾條件 map/reduce map: map(func,li)函數接收兩個參數,一個是函數,一個是Iterable, map將傳入的函數依次做用到序列的每一個元素,並把結果做爲新的Iterator返回。 map映射函數, 這裏面的map(lambda x:x*x,ls) ,第一個lambda x:x*x是map的第一個參數函數內存地址,第二個ls是可迭代對象,和filter是同樣的位置傳參數li111 = [1,2,3,4] map應用 1.將li111 = [1,2,3,4]快速轉成str print(list(map(str,li111))) #將int快速轉成str 2. ls= [1,2,3,4,5] print(list(map(lambda x:x*x,ls))) reduce:(感受有點像遞歸函數)
reduce把一個函數做用在一個序列[x1, x2, x3, ...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素作累積計算 第一個參數是函數的內存地址,第二個參數是可迭代對象第一個參數是函數的內存地址,第二個參數是可迭代對象 他調用的方法中必需要兩個參數,第一個參數一直使用return出來的值,第二個參數是循環可迭代對選對象的元素 from functools import reduce li111 = [1,2,3,4] def func23(x,y): return x*10 +y print(reduce(func23,li111))
zip:函數是python代碼中很是經常使用的一個操做。
其以可迭代對象爲輸入參數,將可迭代對象裏元素分別取出再組合成一個個元組,返回一個列表。
a = ['name', 'age', 'sex']
b = ['alex', 35, 'Male']
print(dict(zip(a,b)))
什麼狀況須要加list()函數轉化一下?
map()傳入的第一個參數是f,即函數對象自己。因爲結果r是一個Iterator,Iterator是惰性序列,所以經過list()函數讓它把整個序列都計算出來並返回一個list。
9.內置函數學習
https://docs.python.org/zh-cn/3.7/library/functions.html
文章:https://www.cnblogs.com/eric_yi/p/7255455.html
文章:https://www.cnblogs.com/cicaday/p/python-decorator.html
文章:https://yiyibooks.cn/xx/python_352/library/index.html