日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python进阶:搞懂装饰器和切面编程

發布時間:2023/12/15 python 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python进阶:搞懂装饰器和切面编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

學習目標:

裝飾器、切面編程,實際使用體會。
紙上學來終覺淺


裝飾器和切面編程:

常見的函數,我們一般的返回值一個常見的數值或者列表,比如:

def mysum(a,b):return a + b result = mysum(1,2) print(result)

mysum函數返回的是整數1+2的值,為3.
但是python神奇的地方就是,函數的返回值,可以是另一個函數。比如:

def mysum_log():print('input two number for sum ')def mysum(a,b):return a + breturn mysum mysum2= mysum_log() print(mysum2(1,2))

這樣,mysum_log的函數值是一個函數,賦給了變量mysum2,然后print直接用mysum2(1,2)就可以運行函數.此時的mysum2函數有點類似于mysum的功能,但是增加了print功能。
運行結果:

input two number for sum 3

我們其實可以把變量mysum2直接改成mysum,改一下名字而已,結果就有點神奇了:

def mysum_log():print('input two number for sum ')def mysum(a,b):return a + breturn mysum mysum= mysum_log() print(mysum(1,2))

這樣我們看起來像調用了mysum函數,但實際上我們還多了打印日志的print功能。業界成這個叫閉包–鬼知道為啥要叫這么個名字,還以為包pi有關。
這有什么用呢?單純看沒啥用,但是當這個mysum方式最初是別人寫的,而且別人不愿意改他的函數,可以通過這種方式豐富函數的功能。
舉個例子,隔壁老王寫了個函數:

def laowangsum(a, b):return a ^ 2 + b ^ 2

laowangsum的功能是求平方和,但是沒有解釋,會讓人產生誤解,你叫老王修改函數,增加注釋,他懶不愿意動,怎么辦?
此時你想到能不能偷梁換柱,幫他增加點注釋,讓你的函數調用laowangsum會添加注釋log。于是:

def laowangsum(a, b):return a ^ 2 + b ^ 2def mysum_log():print('老王寫的sum函數,實際是兩個數平方和 ')return laowangsumlaowangsum = mysum_log() print(laowangsum(1, 2))

你調用的laowangsum函數,實際上多運行了你的注釋,偷偷改了老王的函數的功能。這個是閉包的作用。
另一個需求:我們要求對每個函數都打印出日志信息,以便于錯誤時定位是哪個函數出了問題。或者進行函數大屏監控,怎么辦?
為每個函數都加入一個寫log的代碼?重復性太高,我們想辦法抽象起來,既然閉包可以改變函數功能,那用閉包就可以實現,但是現在的閉包需要寫明具體函數,不可能以后新增一個函數都去改一下閉包函數。此時就需要裝飾器,也叫切面編程。簡單來講,我把一個代表函數的變量傳進閉包函數,然后這個閉包函數就可以自適應傳進去的函數,自動調用它,不用每次新增函數都去修改閉包,只用調用一次閉包函數即可。

import functoolsdef log_decorator(function):@functools.wraps(function)def wrapper(*args,**kwargs):print('log begin')function(*args,**kwargs)print('log end')return wrapper

比如老王的函數定義時,加上一個@log_decorator,就可以自動幫他寫日志,他不用管日志這塊:

import functoolsdef log_decorator(function):@functools.wraps(function)def wrapper(*args,**kwargs):print('log begin')result = function(*args,**kwargs)print('log end')return resultreturn wrapper@log_decorator def laowangsum(a, b):return a ^ 2 + b ^ 2print(laowangsum(1, 2))

運行結果:

log begin log end 7

可以看到老王雖然自己只實現了加法邏輯,但是函數運行時,卻自動多了寫日志的功能,就像函數被砍了兩刀,自動加上了寫log的功能一樣。所以叫切面編程。
而且用print(laowangsum.name)打印出來,laowangsum確實就是老王自己定義的函數,名字沒有變化,沒有被偷梁換柱,因為是@functools.wraps(function)的原因。


裝飾類:

除了函數,還可以用裝飾類,大同小異。把函數替換成類

class log:def __init__(self,func):self.func = funcself.num_calls = 0 #函數調用次數def __call__(self, *args, **kwargs):self.num_calls += 1print('number of calls is :{}'.format(self.num_calls))return self.func(*args, **kwargs)@log def example():print('I am being called')example() example() example()

結果:

number of calls is :1 I am being called number of calls is :2 I am being called number of calls is :3 I am being called

log類自動幫助統計了函數被調用次數。


結論:

裝飾器經常用在:
1、 寫日志
2、統計運行時間
3、 校驗輸入數據的有效性和用戶認證等

總結

以上是生活随笔為你收集整理的python进阶:搞懂装饰器和切面编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。