首頁 >後端開發 >Python教學 >Python裝飾器原理與用法分析

Python裝飾器原理與用法分析

不言
不言原創
2018-05-02 15:59:202358瀏覽

這篇文章主要介紹了Python裝飾器原理與用法,結合實例形式分析了Python裝飾器的概念、原理、使用方法及相關操作注意事項,需要的朋友可以參考下

本文實例講述了Python裝飾器原理與用法。分享給大家供大家參考,具體如下:

1、裝飾器的本質是函數,主要用來裝飾其他函數,也就是為其他函數新增附加功能

2、裝飾器的原則:

(1) 裝飾器不能修改被裝飾的函數的原始碼

(2) 裝飾器不能修改被裝飾的函數的呼叫方式

3、實作裝飾器的知識儲備

(1) Python中函數即'變數'

a、變數在Python中的儲存

x='Tomwenxing'
y=x

[說明]:

當Python解釋器遇到語句x='Tomwenxing'時,它主要完成了兩樣工作:

  1.在記憶體中開闢了一片空間用來儲存字串'Tomwenxing'

#  2.在記憶體從創建了一個名為x的變量,並用它指向字串'Tomwenxing'所佔據的記憶體空間(可以理解為房間和房間號碼的關係)

而語句y=x意為將變數x對字串的引用賦值給變數y,即在記憶體中建立一個變數y,並使其指向變數x所指向的記憶體空間

b、函數在Python中的儲存

def test():
  pass

[說明]:

#在Python中,函數的儲存和變數相似,以上面的函數為例,Python解釋其主要做兩件事:

  1.在記憶體中開闢一個記憶體空間,用來儲存函數程式碼的字串(本例中程式碼只有一句:pass)

  2.在記憶體中建立一個變數test,用來指向儲存函數程式碼字串的記憶體空間(相當於test='函數體')

#因此說在Python中函數即變數

#(2) 高階函數(下面兩個條件滿足任何一個即為高階函數)

a、把一個函數名當做實參傳遞給另一個函數

#[對裝飾器的影響]:達到「在不修改被裝飾函數原始碼的情況下為其添加功能」的效果

import time
def bar():
  time.sleep(2)
  print('in the bar')
def test(func):
  start_time=time.time()
  func()
  stop_time=time.time()
  print('函数的运行时间为:',stop_time-start_time)
test(bar)

運行結果:

in the bar
函數的運行時間為: 2.0021145343780518

b、傳回值中包含函數名稱

[對裝飾器的影響]:達到「不改變函數的呼叫方式「的效果

import time
def bar():
  time.sleep(3)
  print('in the bar')
def test2(func):
  print('新添加的功能')
  return func
bar=test2(bar)
bar()

運行結果:

##新加入的功能

in the bar

(3) 巢狀函數:在一個函數體內用def去宣告一個新的函數(不是呼叫)

def foo():
  print('in the foo')
  def bar(): #声明一个新的函数,而不是调用函数
    print('in the bar')
  bar()
foo()

運行結果:

in the foo

in the bar

4、裝飾器的語法:高階函數巢狀函數=》裝飾器(下面的範例可以用pycharm的偵錯器調試一下,看看程式碼的運行順序)

import time
def timer(func):
  def deco(*args,**kwargs):#使用了不定参数
    start_time=time.time()
    res=func(*args,**kwargs) #运行函数
    stop_time=time.time()
    print('运行时间:',stop_time-start_time)
    return res # 若无返回值,则返回None
  return deco
@timer #等价于test1=timer(test1)=deco,即test1()=deco()
def test1():
  time.sleep(3)
  print('in the test1')
@timer #等价于test2=timer(test2)=deco,即test2(name)=deco(name)
def test2(name):
  time.sleep(3)
  print('in the test2',name)
test1()
print('-------------分界线------------------------')
test2('Tomwenxing')

運行結果:

in the test1

運行時間: 3.0001718997955322
-------- -----分界線------------------------
in the test2 Tomwenxing
運行時間: 3.000171422958374

5、帶參數的裝飾器

# -*- coding:utf-8 -*-
user,passwd='Tomwenxing','123'
#如装饰器带参数,一般是三层嵌套
def auth(auth_type): #第一层的参数是装饰器的参数
  def outer_wrapper(func):#第二层的参数是装饰器要装饰的目标函数
    def wrapper(*args,**kwargs):#第三次的参数是目标函数的参数
      if auth_type=='local':
        username = input('Username:').strip()
        password = input('Password:').strip()
        if user == username and passwd == password:
          print('用户Tomwenxing已经成功登录!')
          res = func(*args, **kwargs) #运行目标函数
          return res
        else:
          exit('用户名或密码有错误')
      elif auth_type=='ldap':
        print('暂不支持这种登录方式!')
    return wrapper
  return outer_wrapper
def index():
  print('欢迎来到index页面')
@auth(auth_type='local') #home=wrapper()
def home(name):
  print('%s,欢迎来到home页面' %name)
  return 'This is home page'
@auth(auth_type='ldap')
def bbs():
  print('欢迎来到bbs页面 ')
index()
print('----------------------分界线-------------------')
print('函数的返回值为:',home('wenxing'))
print('----------------------分界线-------------------')
bbs()

運行結果:

#歡迎來到index頁面

------------ ----------分界線-------------------
Username:Tomwenxing
Password:123
使用者Tomwenxing已經成功登入!
wenxing,歡迎來到home頁面
函數的回傳值為: This is home page
----------------------分界線-------------------
暫時不支援這種登入方式!

相關推薦:

#使用python裝飾器計算函數運行時間

Python迭代器定義與簡單用法分析

以上是Python裝飾器原理與用法分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn