Python3.5裝飾器原理及應用實例詳解
本文實例講述了Python3.5裝飾器原理及應用。分享給大家供大家參考,具體如下:
1、裝飾器:
(1)本質:裝飾器的本質是函數,其基本語法都是用關鍵字def去定義的。
(2)功能:裝飾其他函數,即:為其他函數添加附加功能。
(3)原則:不能修改被裝飾的函數的源代碼,不能修改被裝飾的函數的調用方式。即:裝飾器對待被修飾的函數是完全透明的。
(4)簡單應用:統(tǒng)計函數運行時間的裝飾器
import time
#統(tǒng)計函數運行時間的磚裝飾器
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)實現(xiàn)裝飾器知識儲備:
a、函數即“變量”
b、高階函數
c、函數嵌套
d、高階函數+嵌套函數==》裝飾器
2、裝飾器知識儲備——函數即“變量”
定義一個函數,相當于把函數體賦值給這個函數名。
Python解釋器如何回收變量:采用引用計數。當引用有沒有了時(門牌號不存在),變量就被回收了。
函數的定義也有內存回收機制,與變量回收機制一樣。匿名函數沒有函數名,就會被回收。

變量的使用:先定義再調用,只要在調用之前已經存在(定義)即可;函數即“變量”,函數的使用是一樣的。
函數調用順序:其他的高級語言類似,Python 不允許在函數未聲明之前,對其進行引用或者調用
下面的兩段代碼運行效果一樣:
def bar():
print("in the bar")
def foo():
print("in the foo")
bar()
foo()
#python為解釋執(zhí)行,函數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為解釋執(zhí)行,函數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))
#調用方式發(fā)生改變,不能像原來的方法去調用被修飾的函數(所以不能實現(xiàn)裝飾器的功能)
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程序設計有所幫助。
相關文章
python flask框架實現(xiàn)傳數據到js的方法分析
這篇文章主要介紹了python flask框架實現(xiàn)傳數據到js的方法,結合實例形式分析了前端數據序列化及后臺Flask交互數據返回相關操作技巧,需要的朋友可以參考下2019-06-06
python使用xmlrpclib模塊實現(xiàn)對百度google的ping功能
這篇文章主要介紹了python使用xmlrpclib模塊實現(xiàn)對百度google的ping功能,實例分析了xmlrpclib模塊的相關技巧,需要的朋友可以參考下2015-06-06
Python 解決logging功能使用過程中遇到的一個問題
這篇文章主要介紹了Python 解決logging功能使用過程中遇到的一個問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04

