python 函數名 、閉包 裝飾器 day13
1,函數名的使用。
函數名是函數的名字,本質就是變量,特殊的變量。函數名()加括號就是執行此函數。
1,單獨打印函數名就是此函數的內存地址。
def func1(): print(555) print(func1) # <function func1 at 0x0000027B7CF1A048>
2,函數名的賦值
def func(): print(666) f = func print(f())
3,函數名可以作為容器類數據的元素。
def f1(): print(111) def f2(): print(222) def f3():print(333) def f4(): print(444) li = [] for i in range(1,5): li.append(‘f‘+str(i)) for i in li: eval(i)()
4,函數名可以作為參數。
def f1(): print(666) def f2(x): x() f2(f1)
5,函數名可以作為函數的返回值。
def f1(): print(666) def f2(x): return x f2(f1)()
函數又叫第一類對象(first-class object)指
1,可在運行期創建
2,可用作函數參數或返回值
3,可存入變量的實體。
2,閉包的使用
內部函數包含對外部作用域而非全劇作用域變量的引用,該內部函數稱為閉包函數
#函數內部定義的函數稱為內部函數
def wraaper(): def inner(): print(444) return inner wraaper()() def wraaper(): def inner(): print(555) inner() wraaper()
判斷閉包函數的方法__closure__
def wraaper(): name = ‘taibai‘def inner(): print(name) inner() print(inner.__closure__) wraaper()
#taibai
(<cell at 0x0000025B34990B58: str object at 0x0000025B34E14848>,)
name = ‘老男孩‘ def wraaper(n): def inner(): print(n) inner() print(inner.__closure__) wraaper(name)
老男孩
(<cell at 0x0000024AF7810B58: str object at 0x0000024AF8343990>,)
這個也是閉包。
閉包的作用,當函數開始執行時,如果遇到閉包,它有一個機制,它會永遠開辟一個內存空間,將閉包中的變量等值放入其中,不會隨函數的執行完畢而消失。
from urllib.request import urlopen content = urlopen(‘http://www.cnblogs.com/jin-xin/‘).read().decode(‘utf-8‘) print(content)
from urllib.request import urlopen def index(): ur1 =‘http://www.xiaohua100.cn/index.html‘ def get(): return urlopen(ur1).read() return get() print(index()())
3,裝飾器
裝飾器本質上就是一個python函數,他可以讓其他函數在不需要做任何代碼變動的前提下,增加額外的功能,裝飾器的返回值也是一個函數對象。
裝飾器的應用場景:比如插入日誌,性能測試,事務處理,緩存等等場景。
現在我有一個需求,我想讓你測試這個函數的執行時間,在不改變這個函數代碼的情況下:
import time def func1(): print(‘所有痛苦都會過去‘) def timmer(f): def inner(): start_time = time.time() f() time.sleep(0.3) end_time = time.time() print(‘此函數的執行效率%s‘%(end_time - start_time)) return inner func1 = timmer(func1) func1()
但是如果有多個函數,我都想讓你測試他們的執行時間,你每次是不是都得func1 = timer(func1)?這樣還是有點麻煩,因為這些函數的函數名可能是不相同,有func1,func2,graph,等等,所以更簡單的方法,python給你提供了,那就是語法糖。
import time def timmer(f): def inner(): start_time = time.time() f() time.sleep(0.3) end_time = time.time() print(‘此函數的執行效率%s‘%(end_time - start_time)) return inner @timmer def func1(): print(‘繼續努力加油自己‘) func1()
import time def timmer(f): def inner(*args,**kwargs): start_time = time.time() ret = f(*args,**kwargs) time.sleep(0.3) end_time = time.time() print(‘此函數的執行效率%s‘%(end_time - start_time)) return ret return inner @timmer def func1(a,b): print(‘繼續努力加油自己‘) return 666 print(func1(1,2))
裝飾器的開放關閉原則:
1.對擴展是開放的
為什麽要對擴展開放呢?
我們說,任何一個程序,不可能在設計之初就已經想好了所有的功能並且未來不做任何更新和修改。所以我們必須允許代碼擴展、添加新功能。
2.對修改是封閉的
為什麽要對修改封閉呢?
就像我們剛剛提到的,因為我們寫的一個函數,很有可能已經交付給其他人使用了,如果這個時候我們對其進行了修改,很有可能影響其他已經在使用該函數的用戶。
裝飾器完美的遵循了這個開放封閉原則。
python 函數名 、閉包 裝飾器 day13