Python装饰器原理与用法分析


Posted in Python onApril 30, 2018

本文实例讲述了Python装饰器原理与用法。分享给大家供大家参考,具体如下:

1、装饰器的本质是函数,主要用来装饰其他函数,也就是为其他函数添加附加功能

2、装饰器的原则:

(1) 装饰器不能修改被装饰的函数的源代码

(2) 装饰器不能修改被装饰的函数的调用方式

3、实现装饰器的知识储备

(1) Python中函数即‘变量'

a、变量在Python中的存储

x='Tomwenxing'
y=x

[说明]:

当Python解释器遇到语句x='Tomwenxing'时,它主要完成了两样工作:

1.在内存中开辟了一片空间用来存储字符串‘Tomwenxing'

2.在内存从创建了一个名为x的变量,并用它指向字符串‘Tomwenxing'所占据的内存空间(可以理解为房间和房间号的关系)

Python装饰器原理与用法分析

而语句y=x意为将变量x对字符串的引用赋值给变量y,即在内存中创建一个变量y,并使其指向变量x所指向的内存空间

Python装饰器原理与用法分析

b、函数在Python中的存储

def test():
  pass

[说明]:

在Python中,函数的存储和变量相似,以上面的函数为例,Python解释其主要做两件事:

1.在内存中开辟一个内存空间,用来存储函数代码的字符串(本例中代码只有一句:pass)

2.在内存中创建一个变量test,用来指向存储函数代码字符串的内存空间(相当于test=‘函数体')

Python装饰器原理与用法分析

因此说在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之有点简约的元组
Sep 24 Python
Python Sleep休眠函数使用简单实例
Feb 02 Python
简单的Python的curses库使用教程
Apr 11 Python
使用pyecharts无法import Bar的解决方案
Apr 23 Python
python列表生成式与列表生成器的使用
Feb 23 Python
JavaScript中的模拟事件和自定义事件实例分析
Jul 27 Python
tensorflow: variable的值与variable.read_value()的值区别详解
Jul 30 Python
python numpy元素的区间查找方法
Nov 14 Python
python 使用poster模块进行http方式的文件传输到服务器的方法
Jan 15 Python
python实现批量文件重命名
Oct 31 Python
关于Numpy数据类型对象(dtype)使用详解
Nov 27 Python
pytorch实现mnist数据集的图像可视化及保存
Jan 14 Python
Python中pillow知识点学习
Apr 30 #Python
Python生成器定义与简单用法实例分析
Apr 30 #Python
Python迭代器定义与简单用法分析
Apr 30 #Python
python 实现在txt指定行追加文本的方法
Apr 29 #Python
Python 实现在文件中的每一行添加一个逗号
Apr 29 #Python
python 把文件中的每一行以数组的元素放入数组中的方法
Apr 29 #Python
详谈python3 numpy-loadtxt的编码问题
Apr 29 #Python
You might like
利用php来自动调用不同服务器上的flash
2006/10/09 PHP
手把手教你使用DedeCms V3的在线采集图文教程
2007/04/03 PHP
php使用异或实现的加密解密实例
2013/09/04 PHP
php生成百度sitemap站点地图类函数实例
2014/10/17 PHP
php封装的图片(缩略图)处理类完整实例
2016/10/19 PHP
PHP生成图表pChart的示例解析
2020/07/31 PHP
使用Apache的rewrite
2021/03/09 Servers
js处理json以及字符串的比较等常用操作
2013/09/08 Javascript
如何实现textarea里的不同文本显示不同颜色
2014/01/20 Javascript
深入探寻seajs的模块化与加载方式
2015/04/14 Javascript
Java遍历集合方法分析(实现原理、算法性能、适用场合)
2016/04/25 Javascript
javascript实现简单的on事件绑定
2016/08/23 Javascript
JavaScript学习笔记整理_setTimeout的应用
2016/09/19 Javascript
AngularJs 延时器、计时器实例代码
2017/09/16 Javascript
微信小程序实现slideUp、slideDown滑动效果及点击空白隐藏功能示例
2018/12/11 Javascript
vue组件三大核心概念图文详解
2019/05/30 Javascript
[05:39]2014DOTA2西雅图国际邀请赛 淘汰赛7月14日TOPPLAY
2014/07/14 DOTA
[55:16]Mski vs VGJ.S Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
python利用不到一百行代码实现一个小siri
2017/03/02 Python
Redis使用watch完成秒杀抢购功能的代码
2018/05/07 Python
Python使用numpy模块实现矩阵和列表的连接操作方法
2019/06/26 Python
python使用pip安装模块出现ReadTimeoutError: HTTPSConnectionPool的解决方法
2019/10/04 Python
python 有效的括号的实现代码示例
2019/11/11 Python
python GUI库图形界面开发之PyQt5控件数据拖曳Drag与Drop详细使用方法与实例
2020/02/27 Python
python中for in的用法详解
2020/04/17 Python
python logging.info在终端没输出的解决
2020/05/12 Python
Python浮点型(float)运算结果不正确的解决方案
2020/09/22 Python
经济实惠的豪华背包和行李袋:Packs Project
2018/10/17 全球购物
老教师工作总结的自我评价
2013/09/27 职场文书
竞选班长演讲稿
2013/12/30 职场文书
关于逃课的检讨书
2014/01/23 职场文书
索桥的故事教学反思
2014/02/06 职场文书
摄影专业毕业生求职信
2014/08/05 职场文书
大卫科波菲尔读书笔记
2015/06/30 职场文书
如何书写你的职业生涯规划书?
2019/06/27 职场文书
分析SQL窗口函数之排名窗口函数
2022/04/21 Oracle