溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

python裝飾器的定義及用法

發(fā)布時(shí)間:2021-08-31 16:44:28 來源:億速云 閱讀:265 作者:chen 欄目:編程語言

本篇內(nèi)容主要講解“python裝飾器的定義及用法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“python裝飾器的定義及用法”吧!

  定義:

  本質(zhì)是函數(shù)(裝飾其他函數(shù)),就是為其他函數(shù)添加附加功能。

  原則:

  不能修改被裝飾的函數(shù)的源代碼

  不能修改被裝飾函數(shù)的調(diào)用方式

  先看一個(gè)完整的裝飾器的例子:

  # Author: Mr.Xue

  # 2019.10.23

  """

  實(shí)現(xiàn)裝飾的知識(shí)儲(chǔ)備:

  1、函數(shù)即‘變量’

  2、高階函數(shù)

  3、嵌套函數(shù)

  高階函數(shù)+嵌套函數(shù)--->裝飾器

  """

  import time

  def timmer(func):

  def warpper(*args, **kwargs):

  start_time = time.time()

  func()

  stop_time = time.time()

  print('the func run time is %s' % (stop_time - start_time))

  return warpper

  @timmer

  def test1():

  time.sleep(3)

  print("in the func test1")

  test1()

  1、函數(shù)即“變量”

  函數(shù)在內(nèi)存中的存儲(chǔ)機(jī)制:在內(nèi)存中存儲(chǔ)函數(shù)體,函數(shù)名作為門牌號(hào)

  注:

  python中的回收機(jī)制:不管是函數(shù)還是變量,一但"門牌號(hào)"不存在了,內(nèi)存空間就會(huì)被回收

  2、高階函數(shù)

  符合下面兩個(gè)條件任何一個(gè)的就是高階函數(shù):

  把一個(gè)函數(shù)名作為實(shí)參傳給另一個(gè)函數(shù)

  返回值中包含函數(shù)名

  '''

  第一種高階函數(shù):

  把一個(gè)函數(shù)名作為實(shí)參傳給另一個(gè)函數(shù)

  --> 實(shí)現(xiàn)了不修改被裝飾的函數(shù)bar代碼的情況下為其添加新功能

  '''

  import time

  def bar():

  time.sleep(3)

  print('in the bar')

  def test(func):

  start_time = time.time()

  print(func)

  func() # run function bar

  stop_time = time.time()

  print("the func run time is %s" %(stop_time-start_time))

  test(bar)

  #x = bar # 函數(shù)即'變量'

  #x()

  '''

  第二種高階函數(shù):

  返回值中包含函數(shù)名

  --> 不修改函數(shù)的調(diào)用方式

  '''

  import time

  def bar():

  time.sleep(3)

  print('in the bar')

  def test2(func):

  print(func) # func的內(nèi)存地址

  return func #返回func的內(nèi)存地址

  print(test2(bar))

  bar = test2(bar)

  bar()

  3、嵌套函數(shù)

  在一個(gè)函數(shù)的函數(shù)體中還有一個(gè)用def聲明函數(shù)

  def foo():

  print("in the foo")

  def bar():

  print("in the bar")

  bar()

  foo()

  好啦,理解了上面的三個(gè)知識(shí)點(diǎn)之后,我們來一步步寫一個(gè)裝飾器,首先我們先定義兩個(gè)函數(shù)test1、test2,再給兩個(gè)函數(shù)添加新的功能,計(jì)算這兩個(gè)函數(shù)的運(yùn)行時(shí)間,怎么做呢,先定義一個(gè)高階函數(shù)(上面提到的第一種高階函數(shù)),將這兩個(gè)函數(shù)當(dāng)作參數(shù)傳進(jìn)去。

  import time

  def deco(func):

  start_time = time.time()

  func() # run function bar

  stop_time = time.time()

  print("the func run time is %s" %(stop_time-start_time))

  def test1():

  time.sleep(3)

  print('in the test1')

  def test2():

  time.sleep(3)

  print('in the test2')

  deco(test1)

  deco(test2)

  現(xiàn)在我們完成了裝飾器的原則之一,再不修改源代碼的基礎(chǔ)上給函數(shù)添加了新的功能。

  看上去好像不難呀,接下來,只要我們改進(jìn)代碼,完成不修改函數(shù)的調(diào)用方式的這個(gè)原則,是不是就完成了呢,好,那我們將上面的高階函數(shù)改寫成第二種的高階函數(shù)

  import time

  def deco(func):

  start_time = time.time()

  return func # 返回func函數(shù)的內(nèi)存地址

  stop_time = time.time()

  print("the func run time is %s" %(stop_time-start_time))

  def test1():

  time.sleep(3)

  print('in the test1')

  def test2():

  time.sleep(3)

  print('in the test2')

  test1 = deco(test1)

  test2 = deco(test2)

  test1() #沒有修改調(diào)用方式,新功能卻不見了

  test2() #沒有修改調(diào)用方式

  利用了第二種高階函數(shù)之后,我們完成了裝飾器的另外一個(gè)原則,沒有改變函數(shù)的調(diào)用方式,但是發(fā)現(xiàn)新功能卻沒有加上去,這時(shí)候只用高階函數(shù)來實(shí)現(xiàn)裝飾器好像有點(diǎn)困難啊,怎么辦呢?好像進(jìn)入死循環(huán)了呀。

  不知道大家注意到?jīng)]有,在上面那個(gè)裝飾器的例子里面,有一行寫著,“高階函數(shù)+嵌套函數(shù)—>裝飾器”,哦,那是不是我們?cè)俑銈€(gè)嵌套函數(shù)就可以了呢,按照這個(gè)思路,我們繼續(xù)往下走。

  import time

  def timer(func):

  def deco():

  start_time = time.time()

  func() # 調(diào)用func函數(shù)

  stop_time = time.time()

  print("the func run time is %s" %(stop_time-start_time))

  return deco

  def test1():

  time.sleep(3)

  print('in the test1')

  def test2():

  time.sleep(3)

  print('in the test2')

  test1 = timer(test1)

  test2 = timer(test2)

  test1() #沒有修改調(diào)用方式,新功能也加上去了

  test2() #沒有修改調(diào)用方式,新功能也加上去了

  哇哦,現(xiàn)在就已經(jīng)完成了裝飾器了,只不過調(diào)用方式看上去比較lower而已,只要修改成標(biāo)準(zhǔn)寫法就ok了。

  怎么做呢,在要被裝飾的函數(shù)頭部,加上"@裝飾器名字",就好啦。

  import time

  def timer(func):

  def deco():

  start_time = time.time()

  func() # 調(diào)用func函數(shù)

  stop_time = time.time()

  print("the func run time is %s" %(stop_time-start_time))

  return deco

  @timer # test1 = timer(test1)

  def test1():

  time.sleep(3)

  print('in the test1')

  @timer

  def test2():

  time.sleep(3)

  print('in the test2')

  test1()

  test2()

  只是現(xiàn)在我們寫的這個(gè)裝飾器和上面那個(gè)還有一點(diǎn)區(qū)別,我們的裝飾器沒有參數(shù),而上面的那個(gè)卻有,接下來,我們繼續(xù)完善完善。鄭州人流多少錢 http://mobile.zyyyzz.com/

  給我們的內(nèi)嵌函數(shù)加上兩個(gè)非固定參數(shù),這樣就可以接收參數(shù)了,如下:

  import time

  def timer(func):

  def deco(*args, **kwargs):

  start_time = time.time()

  func(*args, **kwargs) # 調(diào)用func函數(shù)

  stop_time = time.time()

  print("the func run time is %s" %(stop_time-start_time))

  return deco

  @timer # test1 = timer(test1)

  def test1():

  time.sleep(3)

  print('in the test1')

  @timer

  def test2(name, age):

  time.sleep(3)

  print('in the test2', name, age)

  test1()

  test2("xue", 24)

  ok, all finish!

  現(xiàn)在我們用裝飾器寫一個(gè)網(wǎng)站頁面的需求:比如說,一共20個(gè)網(wǎng)站,其中除了首頁不需要驗(yàn)證可以直接顯示外,其他的都需要驗(yàn)證用戶名密碼才可以顯示。

  # Author: Mr.Xue

  # 2019.10.24

  import time

  user, passwd = 'xue', 'abc123'

  def auth(auth_type):

  print("auth_type: ", auth_type)

  def outer_warpper(func):

  def warpper(*args, **kwargs):

  print("warpper func args:", *args, **kwargs)

  if auth_type == 'local':

  username = input("Username: ")

  password = input("Password: ")

  if user == username and passwd == password:

  print("\033[32;1mUser has passed authentication\033[0m")

  res = func(*args, **kwargs)

  return res

  else:

  print("\033[31;1mInvalid username or password\033[0m")

  elif auth_type == 'ldap':

  print('bu hui gao mao xian')

  return warpper

  return outer_warpper

  def index():

  print("in the index")

  @auth(auth_type='local') #home = warpper(home) -> warpper

  def home():

  print("in the home")

  return 'from home'

  @auth(auth_type='ldap')

  def bbs():

  print('in the bbs')

  index()

  print(home())

  bbs()

到此,相信大家對(duì)“python裝飾器的定義及用法”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI