python中裝飾器(語法糖)概念


“”“”

什么是裝飾器?

"""

還是通過一個例子來慢慢說明

先看下面的例子

def func_1(x):

  return x*2

 

def fun_2(x):

  return x*3

 

def fun_3(x, y i, j):

  return x(i)+y(j)

 

r = func_3(func_1,func_2,2,3)  #把函數引用作為參數傳遞給func_3

print(r)

#通過上面的例子明白:函數的參數可以是函數,也可以是一個類,其實可以是任何類型

 

def runtime_noargs():

  pass

 

@runtime_noargs #這里就是一個裝飾器,裝飾器就是一個閉包函數,回憶下上篇文章的閉包感念

def function_demo1()

  print("demo1函數被運行")

那么是如何把某種功能附加給上面的裝飾器,讓它幫助被裝飾的函數實現某種功能的呢?

我們先對裝飾器函數進行修改

import time

def runtime_noargs(function_name): #將來這里的function_name接受被裝飾的函數名

  def wrapper():

    start_time = time.time()

    function_name() #在這里執行被裝飾器裝飾的函數

    end_time = time.time()

    print(end_time - start_time)

  return wrapper

 

@runtime_noargs #當裝飾器用來裝飾某函數時,被裝飾的函數名被自動傳參給裝飾器函數

def function_demo1()

  time.sleep(1)

  print("demo1函數被運行")

 

function_demo1() #可以使用debug單步運行模式來看看函數的具體執行步驟

上面是一個沒有參數的函數,通過裝飾器來裝飾的,那么有參數的函數如何通過裝飾器來裝飾呢?

 

def args_is_string(function_name):

  def wrapper(a):

    t=type(a)

    if not isinstance(t(), str):

      print("參數錯誤")

    else:

      funtion_name(a)

  return wrapper

 

@args_is_string #通過一個裝飾器函數來限制被裝飾函數輸入的參數只能是字符串

def function_demo2(args): #函數里的參數和裝飾器函數里的內部函數wrapper參數對應,這樣              print(args)                 #args參數就自動傳給了裝飾器中內部函數的參數a上,這是python的                                               #規則

 

function_demo2("aaaa")

上面的例子中,被裝飾的函數只能傳一個參數,那么要傳多個參數呢?

通過一個例子來說明如何實現多個參數的函數的是如何被裝飾的

def many_args(function_name):

  def wrapper(*args):

    print(*args)   #不定長參數這里一個*,打印時需要

    function_name(*args)

  return wrapper

 

@many_args

def function_demo3(*args)  #*args可以接受不定長參數,可以接受若干個參數

  print(*args)

 

function_demo3(1,2,3,4,5,6) 

如果關鍵字參數這種怎么辦呢? 

def dict_args(funtion_name):

  def wrapper(**kwargs):

    print(kwargs) #不定長字典類型的參數,兩個*,在打印時不需要加*,注意和上面的區別

    function_name(**kwargs)

  return wrapper

 

@dict_args

def function_demo4(**kwargs): #**kwargs用來傳不定長的字典形式參數

  print(kwargs)

 

funtion_demo4(name = "fang", age = 10, address = "北京")

如果是混合型的參數呢?

def combo_args(function_name):

  def wrapper(*args, **kwargs):

    print(*args,kwargs)

  return warpper

 

@combo_args

def function_demo5(*args, **kwargs):

  pass

 

function_demo5(1,2,name="fang",age = "10",address="北京")

上面是裝飾器的基本使用方法。

再介紹一種進階版的裝飾器,監控函數運行是否超時

def max_runtime(function_time);

  def out_wrapper(funtion_name):

    def wrapper(*args, **kwargs):

      start_time = time.time()

      i = function_name(*args,**kwargs)  #如果函數需要返回值,這里必須由接住函數                                                                                  #返回值

      end_time = time.time()

      use_time = end_time - start_time

      if use_time > timeout:

        raise RuntimeError("函數運行超時")

      return i  #這里必須把函數返回值返回去,即便在被裝飾的函數本體里已經寫了                                           #return

    return wrapper

  return out_wrapper

 

@max_runtime(timeout=1)

def function_demo6(*args, **kwargs):

  time.sleep(2)

  print("demo6運行")

  return 1

 

result = function_demo6()

print(result)

 

 

上面的這個例子告訴我們,裝飾器后面帶參數時,裝飾器的閉包函數體就要多寫一層函數,見上圖之間的對應關系。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM