您好,登錄后才能下訂單哦!
本文實例講述了Python3.5裝飾器原理及應用。分享給大家供大家參考,具體如下:
1、裝飾器:
(1)本質:裝飾器的本質是函數,其基本語法都是用關鍵字def去定義的。
(2)功能:裝飾其他函數,即:為其他函數添加附加功能。
(3)原則:不能修改被裝飾的函數的源代碼,不能修改被裝飾的函數的調用方式。即:裝飾器對待被修飾的函數是完全透明的。
(4)簡單應用:統計函數運行時間的裝飾器
import time #統計函數運行時間的磚裝飾器 def timmer(func): def warpper(*args,**kwargs): strat_time = time.time() func() stop_time = time.time() print("the func run time is %s" %(stop_time-strat_time)) return warpper @timmer def test1(): time.sleep(3) print("in the test1") test1()
運行結果:
in the test1
the func run time is 3.000171661376953
(5)實現裝飾器知識儲備:
a、函數即“變量”
b、高階函數
c、函數嵌套
d、高階函數+嵌套函數==》裝飾器
2、裝飾器知識儲備——函數即“變量”
定義一個函數,相當于把函數體賦值給這個函數名。
Python解釋器如何回收變量:采用引用計數。當引用有沒有了時(門牌號不存在),變量就被回收了。
函數的定義也有內存回收機制,與變量回收機制一樣。匿名函數沒有函數名,就會被回收。
變量的使用:先定義再調用,只要在調用之前已經存在(定義)即可;函數即“變量”,函數的使用是一樣的。
函數調用順序:其他的高級語言類似,Python 不允許在函數未聲明之前,對其進行引用或者調用
下面的兩段代碼運行效果一樣:
def bar(): print("in the bar") def foo(): print("in the foo") bar() foo() #python為解釋執行,函數foo在調用前已經聲明了bar和foo,所以bar和foo無順序之分 def foo(): print("in the foo") bar() def bar(): print("in the bar") foo()
運行結果:
in the foo
in the bar
in the foo
in the bar
注意:python為解釋執行,函數foo在調用前已經聲明了bar和foo,所以bar和foo無順序之分
原理圖為:
3、裝飾器知識儲備——高階函數
滿足下列其中一種即可稱之為高階函數:
a、把一個函數名當做實參傳遞給另一個函數(在不修改被裝飾函數的情況下為其添加附加功能)
b、返回值中包含函數名(不修改函數的調用方式)
(1)高階函數示例:
def bar(): print("in the bar") def test1(func): print(func) #打印門牌號,即內存地址 func() test1(bar) #門牌號func=bar
運行結果:
<function bar at 0x00BCDFA8>
in the bar
(2)高階函數的妙處——把一個函數名當做實參傳遞給另一個函數(在不修改被裝飾函數的情況下為其添加附加功能)
import time def bar(): time.sleep(3) print("in the bar") #test2在不修改被修飾函數bar的代碼時添加了附加的及時功能 def test2(func): start_time = time.time() func() #run bar stop_time = time.time() print("the func run time is %s " %(stop_time-start_time)) #調用方式發生改變,不能像原來的方法去調用被修飾的函數(所以不能實現裝飾器的功能) test2(bar) #bar()
運行結果:
in the bar
the func run time is 3.000171661376953
(3)高階函數的妙處——返回值中包含函數名(不修改函數的調用方式)
import time def bar(): time.sleep(3) print("in the bar") def test3(func): print(func) return func bar = test3(bar) bar() #run bar
運行結果:
<function bar at 0x00BADFA8>
in the bar
4、裝飾器知識儲備——嵌套函數
#函數嵌套 def foo(): print("in the foo") def bar(): #bar函數具有局部變量的特性,不能在外部調用,只能在內部調用 print("in the bar") bar() foo()
運行結果:
in the foo
in the bar
裝飾器應用——模擬網站登錄頁面,訪問需要認證登錄頁面
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:ZhengzhengLiu #模擬網站,訪問頁面和部分需要登錄的頁面 import timer user,passwd = "liu","liu123" def auth(func): def wrapper(*args,**kwargs): username = input("Username:").strip() password = input("Password:").strip() if username == user and password == passwd: print("\033[32;1mUser has passed authentication!\033[0m") res = func(*args,**kwargs) print("-----after authentication---") return res else: exit("\033[31;1mInvalid username or password!\033[0m") return wrapper def index(): print("welcome to index page!") @auth def home(): print("welcome to index home!") return "from home" @auth def bbs(): print("welcome to index bbs!") #函數調用 index() print(home()) bbs()
運行結果:
welcome to index page!
Username:liu
Password:liu123
User has passed authentication!
welcome to home page!
-----after authentication---
from home
Username:liu
Password:liu123
User has passed authentication!
welcome to bbs page!
-----after authentication---
裝飾器帶參數
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:ZhengzhengLiu #模擬網站,訪問頁面和部分需要登錄的頁面,多種認證方式 import timer user,passwd = "liu","liu123" def auth(auth_type): print("auth func:",auth_type) def outer_wrapper(func): def wrapper(*args, **kwargs): print("wrapper func args:",*args, **kwargs) if auth_type == "local": username = input("Username:").strip() password = input("Password:").strip() if username == user and password == passwd: print("\033[32;1mUser has passed authentication!\033[0m") #被裝飾的函數中有返回值,裝飾器中傳入的參數函數要有返回值 res = func(*args, **kwargs) #from home print("-----after authentication---") return res else: exit("\033[31;1mInvalid username or password!\033[0m") elif auth_type == "ldap": print("ldap....") return wrapper return outer_wrapper def index(): print("welcome to index page!") @auth(auth_type="local") #利用本地登錄 home = wrapper() def home(): print("welcome to home page!") return "from home" @auth(auth_type="ldap") #利用遠程的ldap登錄 def bbs(): print("welcome to bbs page!") #函數調用 index() print(home()) #wrapper() bbs()
運行結果:
更多關于Python相關內容可查看本站專題:《Python數據結構與算法教程》、《Python Socket編程技巧總結》、《Python函數使用技巧總結》、《Python字符串操作技巧匯總》及《Python入門與進階經典教程》
希望本文所述對大家Python程序設計有所幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。