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简单的函数定义和用法实例
May 07 Python
举例详解Python中yield生成器的用法
Aug 05 Python
TensorFlow实现Batch Normalization
Mar 08 Python
python 2.7.14安装图文教程
Apr 08 Python
Python实现iOS自动化打包详解步骤
Oct 03 Python
python实现扫描局域网指定网段ip的方法
Apr 16 Python
Python中新式类与经典类的区别详析
Jul 10 Python
Python进程,多进程,获取进程id,给子进程传递参数操作示例
Oct 11 Python
pytorch-RNN进行回归曲线预测方式
Jan 14 Python
pyCharm 设置调试输出窗口中文显示方式(字符码转换)
Jun 09 Python
Python实现文件压缩和解压的示例代码
Aug 12 Python
用基于python的appium爬取b站直播消费记录
Apr 17 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
《APMServ 5.1.2》使用图解
2006/10/23 PHP
discuz免激活同步登入代码修改方法(discuz同步登录)
2013/12/24 PHP
浅析php工厂模式
2014/11/25 PHP
javascript html 静态页面传参数
2009/04/10 Javascript
Jquery Ajax 学习实例2 向页面发出请求 返回JSon格式数据
2010/03/15 Javascript
JavaScript获取多个数组的交集简单实例
2013/11/11 Javascript
教你如何在 Javascript 文件里使用 .Net MVC Razor 语法
2014/07/23 Javascript
jQuery中prepend()方法用法实例
2014/12/25 Javascript
JavaScript使用Prototype实现面向对象的方法
2015/04/14 Javascript
Javascript连接Access数据库完整实例
2015/08/03 Javascript
JS基于myFocus库实现各种功能的tab选项卡切换效果
2015/09/19 Javascript
Express实现前端后端通信上传图片之存储数据库(mysql)傻瓜式教程(一)
2015/12/10 Javascript
JavaScript自学笔记(必看篇)
2016/06/23 Javascript
jQuery Validate 相关参数及常用的自定义验证规则
2017/03/06 Javascript
Javascript刷新页面的实例
2017/09/23 Javascript
在vue项目中安装使用Mint-UI的方法
2017/12/27 Javascript
MUI 实现侧滑菜单及其主体部分上下滑动的方法
2018/01/25 Javascript
微信小程序实现循环动画效果
2018/07/16 Javascript
vue2.0 路由模式mode="history"的作用
2018/10/18 Javascript
react-router4按需加载(踩坑填坑)
2019/01/06 Javascript
JavaScript设计模式之责任链模式实例分析
2019/01/16 Javascript
JS端基于download.js实现图片、视频时直接下载而不是打开预览
2020/05/09 Javascript
python正则表达式去掉数字中的逗号(python正则匹配逗号)
2013/12/25 Python
python连接MySQL数据库实例分析
2015/05/12 Python
举例讲解Django中数据模型访问外键值的方法
2015/07/21 Python
Python获取昨天、今天、明天开始、结束时间戳的方法
2018/06/01 Python
OpenCV+Python3.5 简易手势识别的实现
2020/12/21 Python
美国卡车、吉普车和SUV零件网站:4 Wheel Parts
2016/11/24 全球购物
巴基斯坦电子产品购物网站:Home Shopping
2017/09/14 全球购物
荷兰手表网站:Watch2Day
2018/07/02 全球购物
秋天的图画教学反思
2014/05/01 职场文书
2015年爱牙日活动总结
2015/02/05 职场文书
2015年酒店客房部工作总结
2015/04/25 职场文书
2015年国庆晚会主持词
2015/07/01 职场文书
二胎满月酒致辞
2015/07/29 职场文书
Java详细解析==和equals的区别
2022/04/07 Java/Android