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

Python裝飾器代碼詳解

 更新時(shí)間:2021年10月27日 14:13:59   作者:凡晨丹心  
這篇文章主要介紹了python 一篇文章搞懂裝飾器所有用法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、理解裝飾器

所有東西都是對(duì)象(函數(shù)可以當(dāng)做對(duì)象傳遞)
由于函數(shù)也是一個(gè)對(duì)象,而且函數(shù)對(duì)象可以被賦值給變量,所以,通過變量也能調(diào)用該函數(shù)。

def function_one():
    print("測(cè)試函數(shù)")
#可以將一個(gè)函數(shù)賦值給一個(gè)變量,比如
foo =function_one #這里沒有在使用小括號(hào),因?yàn)槲覀儾⒉皇窃谡{(diào)用function_one函數(shù),而是在將它放在foo變量里。
foo()
'''
測(cè)試函數(shù)
Process finished with exit code 0
'''

閉包的概念:

1)函數(shù)嵌套

2)內(nèi)部函數(shù)使用外部函數(shù)的變量

3)外部函數(shù)的返回值為內(nèi)部函數(shù)

示例:

def outer_function(message):
    def inner_function():
        print(message)
    return inner_function
func = outer_function("你好")
func() #你好

二、裝飾器原型

裝飾器的作用就是 不修改源代碼以及原函數(shù)調(diào)用方式的情況下 給原函數(shù)增加新的功能。

#將函數(shù)作為參數(shù)傳給另一個(gè)函數(shù)
def decorator_function(original_function):
    def wrapper_function():
    	print('wrapper executed this before {}'.format(original_function.__name__))
        original_function()
    return wrapper_function
    '''
    返回wrapper_function而不是wrapper_function();這是因?yàn)楫?dāng)你把一對(duì)小括號(hào)放在后面,這個(gè)函數(shù)就會(huì)執(zhí)行;
    然而如果你不放括號(hào)在它后面,那它可以被到處傳遞,并且可以賦值給別的變量而不去執(zhí)行它。
	'''
def display():
    print('display function ran')
decorator_display = decorator_function(display)
decorator_display()

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

wrapper executed this before display
display function ran
Process finished with exit code 0

1、不帶參數(shù)的裝飾器

def decorator_function(original_function):
    def wrapper_function():
        print('wrapper executed this before {}'.format(original_function.__name__))
        original_function()
    return wrapper_function
@decorator_function
def display():  #等價(jià)于display =decorator_function(display)
    print('display function ran')
display()

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

wrapper executed this before display
display function ran

Process finished with exit code 0

2.帶參數(shù)的被裝飾的函數(shù)

def decorator_function(original_function):
    def wrapper_function(*args,**kwargs):
        print('wrapper executed this before {}'.format(original_function.__name__))
        original_function(*args,**kwargs)
    return wrapper_function
@decorator_function
def display():
    print('display function ran')
@decorator_function
def display_info(name,age):
    print('display_info ran with arguments ({},{})'.format(name,age))
display()
print('='*50)
display_info('Michal',20)

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

wrapper executed this before display
display function ran
==================================================
wrapper executed this before display_info
display_info ran with arguments (Michal,20)

Process finished with exit code 0

運(yùn)行如下代碼會(huì)出現(xiàn)一個(gè)問題

def decorator_function(original_function):
    def wrapper_function(*args,**kwargs):
        print('wrapper executed this before {}'.format(original_function.__name__))
        original_function(*args,**kwargs)
    return wrapper_function
@decorator_function
def display():
    print('display function ran')
@decorator_function
def display_info(name,age):
    print('display_info ran with arguments ({},{})'.format(name,age))
display_info = decorator_function(display_info)
print(display_info.__name__)

wrapper_function

Process finished with exit code 0

輸出的應(yīng)該是display_info,這里的函數(shù)被wrapper_function替代了,重寫了我們函數(shù)的名字和注釋文檔(docstring)。Python中可以使用functools.wraps來解決這個(gè)問題。

from functools import wraps
def decorator_function(original_function):
    @wraps(original_function)
    def wrapper_function(*args,**kwargs):
        print('wrapper executed this before {}'.format(original_function.__name__))
        original_function(*args,**kwargs)
    return wrapper_function
@decorator_function
def display():
    print('display function ran')
@decorator_function
def display_info(name,age):
    print('display_info ran with arguments ({},{})'.format(name,age))
display_info = decorator_function(display_info)
print(display_info.__name__)

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

display_info

Process finished with exit code 0

3.帶參數(shù)的裝飾器

在函數(shù)中嵌入裝飾器

from functools import wraps
def logit(logfile='out.log'):
    def logging_decorator(func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + " was called"
            print(log_string)
            # 打開logfile,并寫入內(nèi)容
            with open(logfile, 'a') as opened_file:
                # 現(xiàn)在將日志打到指定的logfile
                opened_file.write(log_string + '\n')
            return func(*args, **kwargs)
        return wrapped_function
    return logging_decorator
@logit()
def myfunc1():
    pass
myfunc1()
# Output: myfunc1 was called
# 現(xiàn)在一個(gè)叫做 out.log 的文件出現(xiàn)了,里面的內(nèi)容就是上面的字符串
@logit(logfile='func2.log')
def myfunc2():
    pass
myfunc2()
# Output: myfunc2 was called
# 現(xiàn)在一個(gè)叫做 func2.log 的文件出現(xiàn)了,里面的內(nèi)容就是上面的字符串

4.使用類作為裝飾器

class myDecorator(object):
     def __init__(self, f):
         print("inside myDecorator.__init__()")
         f() # Prove that function definition has completed
     def __call__(self):
         print("inside myDecorator.__call__()")
 ​
 @myDecorator
 def aFunction():
     print("inside aFunction()")
 ​
 print("Finished decorating aFunction()")
 ​
 aFunction()

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

inside myDecorator.__init__()
inside aFunction()
Finished decorating aFunction()
inside myDecorator.__call__()
Process finished with exit code 0

被裝飾后的函數(shù)aFunction()實(shí)際上已經(jīng)是類myDecorator的對(duì)象。當(dāng)再調(diào)用aFunction()函數(shù)時(shí),實(shí)際上就是調(diào)用類myDecorator的對(duì)象,因此會(huì)調(diào)用到類myDecorator的__call__()方法。

因此使用類作為裝飾器裝飾函數(shù)來對(duì)函數(shù)添加一些額外的屬性或功能時(shí),一般會(huì)在類的__init__()方法中記錄傳入的函數(shù),再在__call__()調(diào)用修飾的函數(shù)及其它額外處理。

class entryExit(object):
     def __init__(self, f):
         self.f = f
     def __call__(self):
         print("Entering", self.f.__name__)
         self.f()
         print("Exited", self.f.__name__)
 ​
 @entryExit
 def func1():
     print("inside func1()")
 ​
 @entryExit
 def func2():
     print("inside func2()")
 ​
 func1()
 func2()

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

Entering func1
inside func1()
Exited func1
Entering func2
inside func2()
Exited func2

Process finished with exit code 0

5.使用對(duì)象作為裝飾器

空參:

from functools import wraps
class decorator_class:
    def __init__(self):
        print('執(zhí)行decorator_class類的__init__()方法')
    def __call__(self, original_function):
        print('執(zhí)行decorator_class類的__call__()方法')
        @wraps(original_function)
        def wrapped_function(*args, **kwargs):
            print('call method executed this before {}'.format(original_function.__name__))
            print('執(zhí)行' + original_function.__name__ + '()')
            original_function(*args, **kwargs)
            print(original_function.__name__ + '()執(zhí)行完畢')
        return wrapped_function
@decorator_class()
def display_info(name,age):
    print('display_info ran with arguments ({},{})'.format(name,age))
display_info('Michael',20)

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

執(zhí)行decorator_class類的__init__()方法
執(zhí)行decorator_class類的__call__()方法
call method executed this before display_info
執(zhí)行display_info()
display_info ran with arguments (Michael,20)
display_info()執(zhí)行完畢

Process finished with exit code 0

帶參數(shù):

from functools import wraps
class decorator_class:
    def __init__(self,arg1, arg2):
        print('執(zhí)行decorator_class類的__init__()方法')
        self.arg1 =arg1
        self.arg2=arg2
    def __call__(self, original_function):
        print('執(zhí)行decorator_class類的__call__()方法')
        @wraps(original_function)
        def wrapped_function(*args, **kwargs):
        	print('執(zhí)行wrapped_function()')
            print('call method executed this before {}'.format(original_function.__name__))
            print('裝飾器參數(shù):', self.arg1, self.arg2)
            print('執(zhí)行' + original_function.__name__ + '()')
            original_function(*args, **kwargs)
            print(original_function.__name__ + '()執(zhí)行完畢')
        return wrapped_function
@decorator_class('Hello', 'World')
def display_info(name,age):
    print('display_info ran with arguments ({},{})'.format(name,age))
display_info('Michael',20)

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

執(zhí)行decorator_class類的__init__()方法
執(zhí)行decorator_class類的__call__()方法
執(zhí)行wrapped_function()
call method executed this before display_info
裝飾器參數(shù): Hello World
執(zhí)行display_info()
display_info ran with arguments (Michael,20)
display_info()執(zhí)行完畢

Process finished with exit code 0

示例2:

from functools import wraps
class logit(object):
    def __init__(self, logfile='out.log'):
        self.logfile = logfile
    def __call__(self, func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            log_string = func.__name__ + " was called"
            print(log_string)
            # 打開logfile并寫入
            with open(self.logfile, 'a') as opened_file:
                # 現(xiàn)在將日志打到指定的文件
                opened_file.write(log_string + '\n')
            # 現(xiàn)在,發(fā)送一個(gè)通知
            self.notify()
            return func(*args, **kwargs)
        return wrapped_function
    def notify(self):
        # logit只打日志,不做別的
        pass
@logit()
def myfunc1():
    pass

6.多層裝飾器的嵌套

#裝飾器1
def decorator1(func):
    #定義裝飾之后的函數(shù)
    def wrapper1():
        # 裝飾器1
        print('1-----裝飾1之前')
        # 調(diào)用基本函數(shù)
        func()
        # 擴(kuò)展功能2
        print('1-----裝飾1之后')
    return wrapper1
#裝飾器2
def decorator2(func):
    #定義裝飾之后的函數(shù)
    def wrapper2():
        # 裝飾器2
        print('2-----裝飾2之前')
        # 調(diào)用基本函數(shù)
        func()
        # 擴(kuò)展功能2
        print('2-----裝飾2之后')
    return wrapper2
#基本函數(shù)
@decorator2   # 第二步:test = decorator2(eat) = test2
@decorator1   # 第一步:test = decorator1(eat)  = test1
def test():
    print('測(cè)試')
#調(diào)用函數(shù)
test()

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

2-----裝飾2之前
1-----裝飾1之前
測(cè)試
1-----裝飾1之后
2-----裝飾2之后

Process finished with exit code 0

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • Python使用sqlite3第三方庫讀寫SQLite數(shù)據(jù)庫的方法步驟

    Python使用sqlite3第三方庫讀寫SQLite數(shù)據(jù)庫的方法步驟

    數(shù)據(jù)庫非常重要,程序的數(shù)據(jù)增刪改查需要數(shù)據(jù)庫支持,python處理數(shù)據(jù)庫非常簡(jiǎn)單,而且不同類型的數(shù)據(jù)庫處理邏輯方式大同小異,下面這篇文章主要給大家介紹了關(guān)于Python使用sqlite3第三方庫讀寫SQLite數(shù)據(jù)庫的方法步驟,需要的朋友可以參考下
    2022-07-07
  • python基礎(chǔ)之匿名函數(shù)詳解

    python基礎(chǔ)之匿名函數(shù)詳解

    這篇文章主要介紹了python基礎(chǔ)之匿名函數(shù)詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)python基礎(chǔ)的小伙伴們有很好的幫助,需要的朋友可以參考下
    2021-04-04
  • 解讀python?cvxpy下SDP問題編程

    解讀python?cvxpy下SDP問題編程

    這篇文章主要介紹了解讀python?cvxpy下SDP問題編程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Python淺析多態(tài)與鴨子類型使用實(shí)例

    Python淺析多態(tài)與鴨子類型使用實(shí)例

    python是一門解釋語言,但是同java等靜態(tài)語言一樣,是可以通過繼承的方式實(shí)現(xiàn)多態(tài)。而且python還有一個(gè)自己的特殊實(shí)現(xiàn)多態(tài)的方法,就是通過鴨子類型,來實(shí)現(xiàn)多態(tài)
    2022-10-10
  • 基于python實(shí)現(xiàn)雙向鏈表

    基于python實(shí)現(xiàn)雙向鏈表

    這篇文章主要為大家詳細(xì)介紹了基于python實(shí)現(xiàn)雙向鏈表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • python eval 轉(zhuǎn)換k m到乘法計(jì)算的操作

    python eval 轉(zhuǎn)換k m到乘法計(jì)算的操作

    這篇文章主要介紹了python eval 轉(zhuǎn)換k m到乘法計(jì)算的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-05-05
  • Pycharm搭建一個(gè)Django項(xiàng)目的方法步驟

    Pycharm搭建一個(gè)Django項(xiàng)目的方法步驟

    本文主要介紹了Pycharm搭建一個(gè)Django項(xiàng)目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • PyTorch平方根報(bào)錯(cuò)的處理方案

    PyTorch平方根報(bào)錯(cuò)的處理方案

    這篇文章主要介紹了PyTorch平方根報(bào)錯(cuò)的處理方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-05-05
  • 在腳本中單獨(dú)使用django的ORM模型詳解

    在腳本中單獨(dú)使用django的ORM模型詳解

    這篇文章主要介紹了在腳本中單獨(dú)使用django的ORM模型詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Python3中對(duì)range()逆序的解釋

    Python3中對(duì)range()逆序的解釋

    這篇文章主要介紹了Python3中對(duì)range()逆序的解釋,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05

最新評(píng)論