中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python中裝飾器怎么用

發布時間:2021-08-03 12:30:31 來源:億速云 閱讀:157 作者:小新 欄目:開發技術

這篇文章將為大家詳細講解有關Python中裝飾器怎么用,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

裝飾器(decorator)功能

  • 引入日志

  • 函數執行時間統計

  • 執行函數前預備處理

  • 執行函數后清理功能

  • 權限校驗等場景

  • 緩存

裝飾器示例

例1:無參數的函數

from time import ctime, sleep

def timefun(func):
 def wrappedfunc():
  print("%s called at %s"%(func.__name__, ctime()))
  func()
 return wrappedfunc

@timefun
def foo():
 print("I am foo")

foo()
sleep(2)
foo()

分析如下:

上面代碼理解裝飾器執行行為可理解成

foo = timefun(foo)

1,foo先作為參數賦值給func后,foo接收指向timefun返回的wrappedfunc
2,調用foo(),即等價調用wrappedfunc()
3,內部函數wrappedfunc被引用,所以外部函數的func變量(自由變量)并沒有釋放
4,func里保存的是原foo函數對象

例2:被裝飾的函數有參數

from time import ctime, sleep

def timefun(func):
 def wrappedfunc(a, b):
  print("%s called at %s"%(func.__name__, ctime()))
  print(a, b)
  func(a, b)
 return wrappedfunc

@timefun
def foo(a, b):
 print(a+b)

foo(3,5)
sleep(2)
foo(2,4)

例3:被裝飾的函數有不定長參數

from time import ctime, sleep

def timefun(func):
 def wrappedfunc(*args, **kwargs):
  print("%s called at %s"%(func.__name__, ctime()))
  func(*args, **kwargs)
 return wrappedfunc

@timefun
def foo(a, b, c):
 print(a+b+c)

foo(3,5,7)
sleep(2)
foo(2,4,9)

例4:裝飾器中的return

from time import ctime, sleep

def timefun(func):
 def wrappedfunc():
  print("%s called at %s"%(func.__name__, ctime()))
  func()
 return wrappedfunc

@timefun
def foo():
 print("I am foo")

@timefun
def getInfo():
 return '----hahah---'

foo()
sleep(2)
foo()


print(getInfo())

執行結果:

foo called at Sun Jun 18 00:31:53 2017
I am foo
foo called at Sun Jun 18 00:31:55 2017
I am foo
getInfo called at Sun Jun 18 00:31:55 2017
None

如果修改裝飾器為return func(),則運行結果:

foo called at Sun Jun 18 00:34:12 2017
I am foo
foo called at Sun Jun 18 00:34:14 2017
I am foo
getInfo called at Sun Jun 18 00:34:14 2017
----hahah---

小結:一般情況下為了讓裝飾器更通用,可以有return

例5:裝飾器帶參數,在原有裝飾器的基礎上,設置外部變量

from time import ctime, sleep

def timefun_arg(pre="hello"):
 def timefun(func):
  def wrappedfunc():
   print("%s called at %s %s"%(func.__name__, ctime(), pre))
   return func()
  return wrappedfunc
 return timefun

@timefun_arg("itcast")
def foo():
 print("I am foo")

@timefun_arg("python")
def too():
 print("I am too")

foo()
sleep(2)
foo()

too()
sleep(2)
too()
可以理解為

foo()==timefun_arg("itcast")(foo)()

例6:類裝飾器

裝飾器函數其實是這樣一個接口約束,它必須接受一個callable對象作為參數,然后返回一個callable對象。在Python中一般callable對象都是函數,但也有例外。只要某個對象重寫了 call() 方法,那么這個對象就是callable的。

class Test():
 def __call__(self):
  print('call me!')

t = Test()
t() # call me
類裝飾器demo


class Test(object):
 def __init__(self, func):
  print("---初始化---")
  print("func name is %s"%func.__name__)
  self.__func = func
 def __call__(self):
  print("---裝飾器中的功能---")
  self.__func()

說明:

1. 當用Test來裝作裝飾器對test函數進行裝飾的時候,首先會創建Test的實例對象,并且會把test這個函數名當做參數傳遞到init方法中
即在init方法中的func變量指向了test函數體
2. test函數相當于指向了用Test創建出來的實例對象
3. 當在使用test()進行調用時,就相當于讓這個對象(),因此會調用這個對象的call方法
4. 為了能夠在call方法中調用原來test指向的函數體,所以在init方法中就需要一個實例屬性來保存這個函數體的引用
所以才有了self.func = func這句代碼,從而在調用__call方法中能夠調用到test之前的函數體

@Test 
def test(): 
print(“—-test—”) 
test() 
showpy()#如果把這句話注釋,重新運行程序,依然會看到”–初始化–”

運行結果如下:

---初始化---
func name is test
---裝飾器中的功能---
----test---

wraps函數

使用裝飾器時,有一些細節需要被注意。例如,被裝飾后的函數其實已經是另外一個函數了(函數名等函數屬性會發生改變)。

添加后由于函數名和函數的doc發生了改變,對測試結果有一些影響,例如:

def note(func):
 "note function"
 def wrapper():
  "wrapper function"
  print('note something')
  return func()
 return wrapper

@note
def test():
 "test function"
 print('I am test')

test()
print(test.__doc__)

運行結果

note something
I am test
wrapper function

所以,Python的functools包中提供了一個叫wraps的裝飾器來消除這樣的副作用。例如:

import functools
def note(func):
 "note function"
 @functools.wraps(func)
 def wrapper():
  "wrapper function"
  print('note something')
  return func()
 return wrapper

@note
def test():
 "test function"
 print('I am test')

test()
print(test.__doc__)

運行結果

note something
I am test
test function

關于“Python中裝飾器怎么用”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

合水县| 平南县| 乐陵市| 大化| 永川市| 乌拉特中旗| 海门市| 小金县| 隆林| 沧源| 嘉峪关市| 定兴县| 陈巴尔虎旗| 凤阳县| 论坛| 南澳县| 时尚| 诏安县| 曲水县| 陈巴尔虎旗| 买车| 伊金霍洛旗| 钦州市| 凤庆县| 堆龙德庆县| 东安县| 亚东县| 宣威市| 德钦县| 崇信县| 嘉义县| 秀山| 同德县| 汽车| 祁连县| 璧山县| 嵊泗县| 呼玛县| 延川县| 安庆市| 凯里市|