欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入了解python裝飾器

 更新時(shí)間:2022年03月02日 10:13:31   作者:xiaotanggao  
這篇文章主要介紹了解python裝飾器,裝飾器定義一個(gè)為其他函數(shù)添加功能的函數(shù),裝飾器就是在不修改裝飾對(duì)象源代碼以及調(diào)用方式的前提下,為裝飾對(duì)象添加新功能,下面和小編一起進(jìn)入文章內(nèi)容了解更多知識(shí),需要的朋友可以參考一下

一、裝飾器

1.相關(guān)知識(shí)點(diǎn)

  • *args:負(fù)責(zé)將多余的位置實(shí)參匯總,賦值給args
  • **kwargs:負(fù)責(zé)將多余的關(guān)鍵字實(shí)參匯總,賦值給kwargs

命名空間與作用域

函數(shù)對(duì)象:

  • 可以把函數(shù)當(dāng)成參數(shù)傳入
  • 可以把函數(shù)當(dāng)做返回值返回

函數(shù)的嵌套定義:在函數(shù)內(nèi)定義函數(shù)

閉包函數(shù):父函數(shù)的返回值為一個(gè)函數(shù),被返回的函數(shù)調(diào)用了父函數(shù)的局部變量,且該函數(shù)可以在父函數(shù)外部執(zhí)行

裝飾器:

裝飾器:定義一個(gè)為其他函數(shù)添加功能的函數(shù)

為什么要使用裝飾器?

  • 開放封閉原則:開放擴(kuò)展功能但封閉源代碼的修改
  • 裝飾器就是在不修改裝飾對(duì)象源代碼以及調(diào)用方式的前提下,為裝飾對(duì)象添加新功能

裝飾器實(shí)現(xiàn):

需求:不修改源代碼,計(jì)算代碼執(zhí)行時(shí)間

 源代碼:

import time
def func0(x):
? ? time.sleep(1)
? ? print(x)
func0(0)

# 方案一:實(shí)現(xiàn)了計(jì)算代碼執(zhí)行時(shí)間的功能,但修改了源代碼,不符合要求
def func1(x):
? ? start = time.time()
? ? time.sleep(1)
? ? print(x)
? ? end = time.time()
? ? print('方案一 運(yùn)行時(shí)間:{}'.format(end - start))
func1(1)

# 方案二:滿足要求,但代碼不具備重用性
start = time.time()
func0(2)
end = time.time()
print('方案二 運(yùn)行時(shí)間:{}'.format(end - start))

# 方案三:將方案二封裝為函數(shù),但修改了函數(shù)的調(diào)用方式,不符合要求
def wrapper():
? ? start = time.time()
? ? func0(3)
? ? end = time.time()
? ? print('方案三 運(yùn)行時(shí)間:{}'.format(end - start))
wrapper()

# 方案四:不修改原函數(shù)的調(diào)用方式
def wrapper(x):
? ? start = time.time()
? ? func0(x)
? ? end = time.time()
? ? print('方案四 運(yùn)行時(shí)間:{}'.format(end - start))
wrapper(4)

# 方案五:方案四參數(shù)被寫死,優(yōu)化方案四
def wrapper(*args, **kwargs):
? ? start = time.time()
? ? func0(*args, **kwargs)
? ? end = time.time()
? ? print('方案五 運(yùn)行時(shí)間:{}'.format(end - start))
wrapper(5)

# 方案六:方案五函數(shù)被寫死,優(yōu)化方案五,但修改了源代碼的調(diào)用方式
def outter(a):
? ? def wrapper(*args, **kwargs):
? ? ? ? start = time.time()
? ? ? ? a(*args, **kwargs)
? ? ? ? end = time.time()
? ? ? ? print('方案六 運(yùn)行時(shí)間:{}'.format(end - start))
? ? return wrapper
f = outter(func0)
f(6)

# 方案七:優(yōu)化方案六(outter即為裝飾器,用于裝飾func0)
def outter(a):
? ? def wrapper(*args, **kwargs):
? ? ? ? start = time.time()
? ? ? ? a(*args, **kwargs)
? ? ? ? end = time.time()
? ? ? ? print('方案七 運(yùn)行時(shí)間:{}'.format(end - start))
? ? return wrapper
func0 = outter(func0)?? ?# 偷梁換柱,調(diào)用者無(wú)感知
func0(7)

運(yùn)行結(jié)果:

0
1
方案一 運(yùn)行時(shí)間:1.001857042312622
2
方案二 運(yùn)行時(shí)間:1.0040733814239502
3
方案三 運(yùn)行時(shí)間:1.0017154216766357
4
方案四 運(yùn)行時(shí)間:1.007995367050171
5
方案五 運(yùn)行時(shí)間:1.0145602226257324
6
方案六 運(yùn)行時(shí)間:1.0046615600585938
7
方案七 運(yùn)行時(shí)間:1.0094060897827148

2.語(yǔ)法糖

  • 使用語(yǔ)法糖,需要將裝飾器放到被裝飾對(duì)象前
# 不使用語(yǔ)法糖
import time
def func0(x):
? ? time.sleep(1)
? ? print(x)
# func0(0)

def outter(a):
? ? def wrapper(*args, **kwargs):
? ? ? ? start = time.time()
? ? ? ? a(*args, **kwargs)
? ? ? ? end = time.time()
? ? ? ? print('運(yùn)行時(shí)間:{}'.format(end - start))
? ? return wrapper
func0 = outter(func0)
func0('hello')

# 使用語(yǔ)法糖
import time

def outter(a):
? ? def wrapper(*args, **kwargs):
? ? ? ? start = time.time()
? ? ? ? a(*args, **kwargs)
? ? ? ? end = time.time()
? ? ? ? print('運(yùn)行時(shí)間:{}'.format(end - start))
? ? return wrapper

@outter # 語(yǔ)法糖,等價(jià)于該行func0 = outter(func0)
def func0(x):
? ? time.sleep(1)
? ? print(x)

func0('hello')
print(func0.__name__)?

運(yùn)行結(jié)果:

hello
運(yùn)行時(shí)間:1.0050427913665771
wrapper

3.裝飾器模板

?# 裝飾器模板
?def decorator_name(x):
? ? ?def wrapper(*args, **kwargs):
? ? ? ? ?# ...新添加的功能...
? ? ? ? ?# 下為調(diào)用原函數(shù)的格式
? ? ? ? ?x(*args, **kwargs)
? ? ?return wrapper

@decorator_name
?def func_name():
? ? ?pass

擴(kuò)展:真正實(shí)現(xiàn)偷梁換柱,調(diào)用者無(wú)感知

  • 不使用裝飾器
?# 不使用裝飾器
import time


def func0(x):
? ? time.sleep(1)
? ? print(x)

func0('hello')
print(func0.__name__) # 查看函數(shù)名?
print(help(func0)) # 查看幫助信息(主要為注釋內(nèi)容)

運(yùn)行結(jié)果:

hello
func0
Help on function func0 in module main:

func0(x)
這是函數(shù)

None

使用裝飾器:

import time

def outter(a):
? ? def wrapper(*args, **kwargs):
? ? ? ? '''這是裝飾器'''
? ? ? ? start = time.time()
? ? ? ? a(*args, **kwargs)
? ? ? ? end = time.time()
? ? ? ? print('運(yùn)行時(shí)間:{}'.format(end - start))
? ? return wrapper

@outter # func0 = outter(func0)
def func0(x):
? ? '''這是函數(shù)'''
? ? time.sleep(1)
? ? print(x)

func0('hello')
print(func0.__name__)
print(help(func0))

運(yùn)行結(jié)果:

hello
運(yùn)行時(shí)間:1.011878490447998
wrapper
Help on function wrapper in module main:

wrapper(*args, **kwargs)
這是裝飾器

None

嘔吼,露餡了

  • 解決方法,將原函數(shù)的屬性和方法,賦值給裝飾器內(nèi)的wrapper
import time

def outter(a):
? ? def wrapper(*args, **kwargs):
? ? ? ? '''這是裝飾器'''
? ? ? ? start = time.time()
? ? ? ? a(*args, **kwargs)
? ? ? ? end = time.time()
? ? ? ? print('運(yùn)行時(shí)間:{}'.format(end - start))
? ? wrapper.__name__ = a.__name__
? ? wrapper.__doc__ = a.__doc__
? ? return wrapper

@outter # func0 = outter(func0)
def func0(x):
? ? '''這是函數(shù)'''
? ? time.sleep(1)
? ? print(x)

func0('hello')
print(func0.__name__)
print(help(func0))

運(yùn)行結(jié)果:

hello
運(yùn)行時(shí)間:1.0030155181884766
func0
Help on function func0 in module main:

func0(*args, **kwargs)
這是函數(shù)

None

但是,函數(shù)有很多屬性和方法,一個(gè)一個(gè)手動(dòng)修改過(guò)于麻煩,甚至可能會(huì)遺漏,但python也提供了解決方法

import time
from functools import wraps

def outter(a):
? ? @wraps(a)
? ? def wrapper(*args, **kwargs):
? ? ? ? '''這是裝飾器'''
? ? ? ? start = time.time()
? ? ? ? a(*args, **kwargs)
? ? ? ? end = time.time()
? ? ? ? print('運(yùn)行時(shí)間:{}'.format(end - start))
? ? # wrapper.__name__ = a.__name__
? ? # wrapper.__doc__ = a.__doc__
? ? return wrapper

@outter # func0 = outter(func0)
def func0(x):
? ? '''這是函數(shù)'''
? ? time.sleep(1)
? ? print(x)

func0('hello')
print(func0.__name__)
print(help(func0))

運(yùn)行結(jié)果:

hello
運(yùn)行時(shí)間:1.0114128589630127
func0
Help on function func0 in module main:

func0(x)
這是函數(shù)

None

4.有參裝飾器

  • 裝飾器內(nèi)需要傳入?yún)?shù),但是由于語(yǔ)法糖的限制,裝飾器只能有一個(gè)參數(shù),并且該參數(shù)僅用來(lái)接收被裝飾對(duì)象的內(nèi)存地址,如何傳入其他參數(shù)?
  • 解決思路:將裝飾器做成閉包函數(shù)
def outter(db_type):
? ? # 裝飾器auth
? ? def auth(x):
? ? ? ? def wrapper(*args, **kwargs):
? ? ? ? ? ? if db_type == 'file':
? ? ? ? ? ? ? ? name = input('請(qǐng)輸入姓名:')
? ? ? ? ? ? ? ? passwd = input('請(qǐng)輸入密碼:')
? ? ? ? ? ? ? ? if name == 'zhangsan' and passwd == '123':
? ? ? ? ? ? ? ? ? ? x(*args, **kwargs)
? ? ? ? ? ? ? ? ? ? print('基于文件認(rèn)證')
? ? ? ? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ? print('用戶名或密碼錯(cuò)誤,認(rèn)證失敗')
? ? ? ? ? ? elif db_type == 'mysql':
? ? ? ? ? ? ? ? x(*args, **kwargs)
? ? ? ? ? ? ? ? print('基于數(shù)據(jù)庫(kù)認(rèn)證')
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? print('未知認(rèn)證方式,不支持')
? ? ? ? return wrapper
? ? return auth

# 函數(shù)
auth = outter(db_type='file')
@auth
def file():
? ? print('hello')


auth = outter(db_type='mysql')
@auth
def mysql():
? ? print('world')

msg = input('請(qǐng)選擇認(rèn)證方式(1=file|2=mysql):').strip()
if msg =='1':
? ? file()
elif msg == '2':
? ? mysql()
else:
? ? print('不支持')
  • 將傳入的參數(shù)寫入語(yǔ)法糖
def outter(db_type):
? ? # 裝飾器auth
? ? def auth(x):
? ? ? ? def wrapper(*args, **kwargs):
? ? ? ? ? ? if db_type == 'file':
? ? ? ? ? ? ? ? name = input('請(qǐng)輸入姓名:')
? ? ? ? ? ? ? ? passwd = input('請(qǐng)輸入密碼:')
? ? ? ? ? ? ? ? if name == 'zhangsan' and passwd == '123':
? ? ? ? ? ? ? ? ? ? x(*args, **kwargs)
? ? ? ? ? ? ? ? ? ? print('基于文件認(rèn)證')
? ? ? ? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ? print('用戶名或密碼錯(cuò)誤,認(rèn)證失敗')
? ? ? ? ? ? elif db_type == 'mysql':
? ? ? ? ? ? ? ? x(*args, **kwargs)
? ? ? ? ? ? ? ? print('基于數(shù)據(jù)庫(kù)認(rèn)證')
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? print('未知認(rèn)證方式,不支持')
? ? ? ? return wrapper
? ? return auth

# 函數(shù)
# auth = outter(db_type='file')
# @auth
@outter(db_type='file')
def file():
? ? print('hello')

# auth = outter(db_type='mysql')
# @auth
@outter(db_type='mysql')
def mysql():
? ? print('world')

msg = input('請(qǐng)選擇認(rèn)證方式(1=file|2=mysql):').strip()
if msg =='1':
? ? file()
elif msg == '2':
? ? mysql()
else:
? ? print('不支持')
  • 模板
# 有參裝飾器模板
def out_decorator_name(x,y,z):
? ? def decorator_name(a):
? ? ? ? def wrapper(*args, **kwargs):
? ? ? ? ? ? # ...新添加的功能...
? ? ? ? ? ? # 下為調(diào)用原函數(shù)的格式
? ? ? ? ? ? a(*args, **kwargs)
? ? ? ? return wrapper
? ? return decorator_name

@out_decorator_name(x,y,z=1)
def func_name():
? ? ?pass

到此這篇關(guān)于深入了解python裝飾器的文章就介紹到這了,更多相關(guān)python裝飾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python實(shí)現(xiàn)給圖片添加文字或圖片水印

    Python實(shí)現(xiàn)給圖片添加文字或圖片水印

    在現(xiàn)今的數(shù)字化時(shí)代,網(wǎng)絡(luò)上的圖片泛濫,盜圖現(xiàn)象也越來(lái)越嚴(yán)重。因此,在發(fā)布文章時(shí),為了保護(hù)自己的原創(chuàng)作品版權(quán),很多人選擇使用水印來(lái)保護(hù)他們的圖片。本文就和大家分享了Python實(shí)現(xiàn)給圖片添加文字或圖片水印的方法,需要的可以收藏一下
    2023-05-05
  • python實(shí)現(xiàn)循環(huán)語(yǔ)句1到100累和

    python實(shí)現(xiàn)循環(huán)語(yǔ)句1到100累和

    這篇文章主要介紹了python循環(huán)語(yǔ)句1到100累和方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • python二叉樹遍歷的實(shí)現(xiàn)方法

    python二叉樹遍歷的實(shí)現(xiàn)方法

    這篇文章主要介紹了python二叉樹遍歷的實(shí)現(xiàn)方法,使用了三種遍歷:先序遍歷,中序遍歷,后序遍歷,方法大家參考使用
    2013-11-11
  • Python戀愛小助手之必拿下

    Python戀愛小助手之必拿下

    小編有個(gè)好兄弟最近在追妹子,跟妹子打得火熱!就差臨門一腳了,這一jio我?guī)兔ρa(bǔ)上去了!他問(wèn)有沒有什么酷炫的表白方式,想要一次成功,表白的方式有許多種今天小編來(lái)給大家?guī)?lái)兩個(gè)不得不同意的表白代碼
    2021-10-10
  • Python實(shí)現(xiàn)分?jǐn)?shù)序列求和

    Python實(shí)現(xiàn)分?jǐn)?shù)序列求和

    今天小編就為大家分享一篇Python實(shí)現(xiàn)分?jǐn)?shù)序列求和,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-02-02
  • Python利用神經(jīng)網(wǎng)絡(luò)解決非線性回歸問(wèn)題實(shí)例詳解

    Python利用神經(jīng)網(wǎng)絡(luò)解決非線性回歸問(wèn)題實(shí)例詳解

    這篇文章主要介紹了Python利用神經(jīng)網(wǎng)絡(luò)解決非線性回歸問(wèn)題,結(jié)合實(shí)例形式詳細(xì)分析了Python使用神經(jīng)網(wǎng)絡(luò)解決非線性回歸問(wèn)題的相關(guān)原理與實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-07-07
  • Python利器openpyxl之操作excel表格

    Python利器openpyxl之操作excel表格

    這篇文章主要給大家介紹了關(guān)于Python利器openpyxl之操作excel表格的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 舉例介紹Python中的25個(gè)隱藏特性

    舉例介紹Python中的25個(gè)隱藏特性

    這篇文章主要介紹了一些Python中的隱藏特性,從stackoverflow的人氣問(wèn)題回答中整理而來(lái),主要以代碼實(shí)際解釋說(shuō)明,需要的朋友可以參考下
    2015-03-03
  • Python存儲(chǔ)或讀取json時(shí)如何引入額外的雙引號(hào)和轉(zhuǎn)義引號(hào)

    Python存儲(chǔ)或讀取json時(shí)如何引入額外的雙引號(hào)和轉(zhuǎn)義引號(hào)

    這篇文章主要介紹了Python存儲(chǔ)或讀取json時(shí)如何引入額外的雙引號(hào)和轉(zhuǎn)義引號(hào)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Python 正則表達(dá)式詳解

    Python 正則表達(dá)式詳解

    這篇文章主要介紹了Python中正則表達(dá)式的詳細(xì)教程,正則表達(dá)式是Python學(xué)習(xí)進(jìn)階當(dāng)中的重要內(nèi)容,需要的朋友可以參考下
    2021-10-10

最新評(píng)論