溫馨提示×

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

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

Python3.5裝飾器原理及應(yīng)用實(shí)例詳解

發(fā)布時(shí)間:2020-09-08 16:34:03 來源:腳本之家 閱讀:116 作者:loveliuzz 欄目:開發(fā)技術(shù)

本文實(shí)例講述了Python3.5裝飾器原理及應(yīng)用。分享給大家供大家參考,具體如下:

1、裝飾器:

(1)本質(zhì):裝飾器的本質(zhì)是函數(shù),其基本語(yǔ)法都是用關(guān)鍵字def去定義的。

(2)功能:裝飾其他函數(shù),即:為其他函數(shù)添加附加功能

(3)原則:不能修改被裝飾的函數(shù)的源代碼,不能修改被裝飾的函數(shù)的調(diào)用方式。即:裝飾器對(duì)待被修飾的函數(shù)是完全透明的。

(4)簡(jiǎn)單應(yīng)用:統(tǒng)計(jì)函數(shù)運(yùn)行時(shí)間的裝飾器

import time
#統(tǒng)計(jì)函數(shù)運(yùn)行時(shí)間的磚裝飾器
def timmer(func):
  def warpper(*args,**kwargs):
    strat_time = time.time()
    func()
    stop_time = time.time()
    print("the func run time is %s" %(stop_time-strat_time))
  return warpper
@timmer
def test1():
  time.sleep(3)
  print("in the test1")
test1()
 

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

in the test1
the func run time is 3.000171661376953

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

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

b、高階函數(shù)

c、函數(shù)嵌套

d、高階函數(shù)+嵌套函數(shù)==》裝飾器

2、裝飾器知識(shí)儲(chǔ)備——函數(shù)即“變量”

定義一個(gè)函數(shù),相當(dāng)于把函數(shù)體賦值給這個(gè)函數(shù)名。

Python解釋器如何回收變量:采用引用計(jì)數(shù)。當(dāng)引用有沒有了時(shí)(門牌號(hào)不存在),變量就被回收了。

函數(shù)的定義也有內(nèi)存回收機(jī)制,與變量回收機(jī)制一樣。匿名函數(shù)沒有函數(shù)名,就會(huì)被回收。

Python3.5裝飾器原理及應(yīng)用實(shí)例詳解

變量的使用:先定義再調(diào)用,只要在調(diào)用之前已經(jīng)存在(定義)即可;函數(shù)即“變量”,函數(shù)的使用是一樣的。

函數(shù)調(diào)用順序:其他的高級(jí)語(yǔ)言類似,Python 不允許在函數(shù)未聲明之前,對(duì)其進(jìn)行引用或者調(diào)用

下面的兩段代碼運(yùn)行效果一樣:

def bar():
  print("in the bar")
def foo():
  print("in the foo")
  bar()
foo()
#python為解釋執(zhí)行,函數(shù)foo在調(diào)用前已經(jīng)聲明了bar和foo,所以bar和foo無順序之分
def foo():
  print("in the foo")
  bar()
def bar():
  print("in the bar")
foo()


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

in the foo
in the bar
in the foo
in the bar

注意:python為解釋執(zhí)行,函數(shù)foo在調(diào)用前已經(jīng)聲明了bar和foo,所以bar和foo無順序之分

原理圖為:

Python3.5裝飾器原理及應(yīng)用實(shí)例詳解

3、裝飾器知識(shí)儲(chǔ)備——高階函數(shù)

滿足下列其中一種即可稱之為高階函數(shù):

a、把一個(gè)函數(shù)名當(dāng)做實(shí)參傳遞給另一個(gè)函數(shù)(在不修改被裝飾函數(shù)的情況下為其添加附加功能)

b、返回值中包含函數(shù)名(不修改函數(shù)的調(diào)用方式)

(1)高階函數(shù)示例:

def bar():
  print("in the bar")
def test1(func):
  print(func)  #打印門牌號(hào),即內(nèi)存地址
  func()
test1(bar)   #門牌號(hào)func=bar

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

<function bar at 0x00BCDFA8>
in the bar

(2)高階函數(shù)的妙處——把一個(gè)函數(shù)名當(dāng)做實(shí)參傳遞給另一個(gè)函數(shù)(在不修改被裝飾函數(shù)的情況下為其添加附加功能)

import time
def bar():
  time.sleep(3)
  print("in the bar")
#test2在不修改被修飾函數(shù)bar的代碼時(shí)添加了附加的及時(shí)功能
def test2(func):
  start_time = time.time()
  func()   #run bar
  stop_time = time.time()
  print("the func run time is %s " %(stop_time-start_time))
#調(diào)用方式發(fā)生改變,不能像原來的方法去調(diào)用被修飾的函數(shù)(所以不能實(shí)現(xiàn)裝飾器的功能)
test2(bar)
#bar()


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

in the bar
the func run time is 3.000171661376953

(3)高階函數(shù)的妙處——返回值中包含函數(shù)名(不修改函數(shù)的調(diào)用方式)

import time
def bar():
   time.sleep(3)
   print("in the bar")
def test3(func):
  print(func)
  return func
bar = test3(bar)
bar()  #run bar


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

<function bar at 0x00BADFA8>
in the bar

4、裝飾器知識(shí)儲(chǔ)備——嵌套函數(shù)

#函數(shù)嵌套
def foo():
  print("in the foo")
  def bar():  #bar函數(shù)具有局部變量的特性,不能在外部調(diào)用,只能在內(nèi)部調(diào)用
    print("in the bar")
  bar()
foo()

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

in the foo
in the bar

裝飾器應(yīng)用——模擬網(wǎng)站登錄頁(yè)面,訪問需要認(rèn)證登錄頁(yè)面

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#模擬網(wǎng)站,訪問頁(yè)面和部分需要登錄的頁(yè)面
import timer
user,passwd = "liu","liu123"
def auth(func):
  def wrapper(*args,**kwargs):
    username = input("Username:").strip()
    password = input("Password:").strip()
    if username == user and password == passwd:
      print("\033[32;1mUser has passed authentication!\033[0m")
      res = func(*args,**kwargs)
      print("-----after authentication---")
      return res
    else:
      exit("\033[31;1mInvalid username or password!\033[0m")
  return wrapper
def index():
  print("welcome to index page!")
@auth
def home():
  print("welcome to index home!")
  return "from home"
@auth
def bbs():
  print("welcome to index bbs!")
#函數(shù)調(diào)用
index()
print(home())
bbs()
 

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

welcome to index page!
Username:liu
Password:liu123
User has passed authentication!
welcome to home page!
-----after authentication---
from home
Username:liu
Password:liu123
User has passed authentication!
welcome to bbs page!
-----after authentication---

裝飾器帶參數(shù)

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#模擬網(wǎng)站,訪問頁(yè)面和部分需要登錄的頁(yè)面,多種認(rèn)證方式
import timer
user,passwd = "liu","liu123"
def auth(auth_type):
  print("auth func:",auth_type)
  def outer_wrapper(func):
    def wrapper(*args, **kwargs):
      print("wrapper func args:",*args, **kwargs)
      if auth_type == "local":
        username = input("Username:").strip()
        password = input("Password:").strip()
        if username == user and password == passwd:
          print("\033[32;1mUser has passed authentication!\033[0m")
          #被裝飾的函數(shù)中有返回值,裝飾器中傳入的參數(shù)函數(shù)要有返回值
          res = func(*args, **kwargs)  #from home
          print("-----after authentication---")
          return res
        else:
          exit("\033[31;1mInvalid username or password!\033[0m")
      elif auth_type == "ldap":
        print("ldap....")
    return wrapper
  return outer_wrapper
def index():
  print("welcome to index page!")
@auth(auth_type="local")    #利用本地登錄 home = wrapper()
def home():
  print("welcome to home page!")
  return "from home"
@auth(auth_type="ldap")    #利用遠(yuǎn)程的ldap登錄
def bbs():
  print("welcome to bbs page!")
#函數(shù)調(diào)用
index()
print(home())   #wrapper()
bbs()

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

Python3.5裝飾器原理及應(yīng)用實(shí)例詳解

更多關(guān)于Python相關(guān)內(nèi)容可查看本站專題:《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python Socket編程技巧總結(jié)》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》及《Python入門與進(jìn)階經(jīng)典教程》

希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。

向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