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 26 Python
Python的time模块中的常用方法整理
Jun 18 Python
python模拟登录并且保持cookie的方法详解
Apr 04 Python
python自动化脚本安装指定版本python环境详解
Sep 14 Python
Queue 实现生产者消费者模型(实例讲解)
Nov 13 Python
Python与人工神经网络:使用神经网络识别手写图像介绍
Dec 19 Python
在mac下查找python包存放路径site-packages的实现方法
Nov 06 Python
python对象转字典的两种实现方式示例
Nov 07 Python
python matplotlib:plt.scatter() 大小和颜色参数详解
Apr 14 Python
python实现马丁策略的实例详解
Jan 15 Python
matplotlib交互式数据光标mpldatacursor的实现
Feb 03 Python
Python实现文本文件拆分写入到多个文本文件的方法
Apr 18 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 If Else(elsefi) 语句
2013/04/07 PHP
php删除指定目录的方法
2015/04/03 PHP
在laravel中使用Symfony的Crawler组件分析HTML
2017/06/19 PHP
浅析PHP类的反射来实现依赖注入过程
2018/02/06 PHP
javascript 语法基础 想学习js的朋友可以看看
2009/12/16 Javascript
JS date对象的减法处理实现代码
2010/12/28 Javascript
深入理解JavaScript高级之词法作用域和作用域链
2013/12/10 Javascript
浅谈JS闭包中的循环绑定处理程序
2014/11/09 Javascript
AngularJS HTML编译器介绍
2014/12/06 Javascript
Bootstrap中CSS的使用方法
2016/02/17 Javascript
Bootstrap实现登录校验表单(带验证码)
2016/06/23 Javascript
angular $watch 一个变量的变化(实例讲解)
2017/08/02 Javascript
layui 图片上传+表单提交+ Spring MVC的实例
2019/09/21 Javascript
vue-cli和v-charts实现可视化图表过程解析
2019/10/08 Javascript
vue element-ui实现动态面包屑导航
2019/12/23 Javascript
关于vue 结合原生js 解决echarts resize问题
2020/07/26 Javascript
JS绘图Flot应用图形绘制异常解决方案
2020/10/16 Javascript
[00:36]DOTA2上海特级锦标赛 Alliance战队宣传片
2016/03/04 DOTA
python爬虫_实现校园网自动重连脚本的教程
2018/04/22 Python
Python爬虫包BeautifulSoup简介与安装(一)
2018/06/17 Python
TensorFlow 合并/连接数组的方法
2018/07/27 Python
Linux系统(CentOS)下python2.7.10安装
2018/09/26 Python
pyinstaller参数介绍以及总结详解
2019/07/12 Python
50行Python代码实现视频中物体颜色识别和跟踪(必须以红色为例)
2019/11/20 Python
详解python破解zip文件密码的方法
2020/01/13 Python
django 解决扩展自带User表遇到的问题
2020/05/14 Python
Python之qq自动发消息的示例代码
2021/02/18 Python
CSS3中的元素过渡属性transition示例详解
2016/11/30 HTML / CSS
CSS3实现莲花绽放的动画效果
2020/11/06 HTML / CSS
Gerry Weber德国官网:优质女性时装,德国最大的时装公司之一
2019/11/02 全球购物
Fossil德国官网:化石手表、手袋、珠宝及配件
2019/12/07 全球购物
Linux如何压缩可执行文件
2013/10/21 面试题
夏季药店促销方案
2014/08/22 职场文书
2015年世界无烟日演讲稿
2015/03/18 职场文书
在 Golang 中实现 Cache::remember 方法详解
2021/03/30 Python
mysql脏页是什么
2021/07/26 MySQL