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的gevent框架下执行异步的Solr查询的教程
Apr 16 Python
python去除文件中空格、Tab及回车的方法
Apr 12 Python
你应该知道的python列表去重方法
Jan 17 Python
python实现单链表中删除倒数第K个节点的方法
Sep 28 Python
python打包生成的exe文件运行时提示缺少模块的解决方法
Oct 31 Python
解决Python内层for循环如何break出外层的循环的问题
Jun 24 Python
pandas如何处理缺失值
Jul 31 Python
使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件及出现问题解决方法
Sep 06 Python
Python 装饰器原理、定义与用法详解
Dec 07 Python
Ranorex通过Python将报告发送到邮箱的方法
Jan 12 Python
python实现猜数游戏
Mar 27 Python
Python接口自动化测试框架运行原理及流程
Nov 30 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
咖啡常见的种类
2021/03/03 新手入门
PHP 简易输出CSV表格文件的方法详解
2013/06/20 PHP
php实现的简单检验登陆类
2015/06/18 PHP
简单谈谈PHP vs Node.js
2015/07/17 PHP
利用javascript移动div层-javascript 拖动层
2009/03/22 Javascript
如何通过javascript操作web控件的自定义属性
2013/11/25 Javascript
js 获取时间间隔实现代码
2014/05/12 Javascript
JSP中使用JavaScript动态插入删除输入框实现代码
2014/06/13 Javascript
js实现带关闭按钮始终显示在网页最底部工具条的方法
2015/03/02 Javascript
jquery.mousewheel实现整屏翻屏效果
2015/08/30 Javascript
BootStrap扔进Django里的方法详解
2016/05/13 Javascript
实现JavaScript的组成----BOM和DOM详解
2016/05/18 Javascript
JS不完全国际化&本地化手册 之 理论篇
2016/09/27 Javascript
微信小程序商城项目之商品属性分类(4)
2017/04/17 Javascript
js,jq,css多方面实现简易下拉菜单功能
2017/05/13 Javascript
iview给radio按钮组件加点击事件的实例
2017/09/30 Javascript
JavaScript实现二叉树的先序、中序及后序遍历方法详解
2017/10/26 Javascript
JavaScript生成简单等差数列
2017/11/28 Javascript
Vue底层实现原理总结
2018/02/17 Javascript
jQuery实现菜单的显示和隐藏功能示例
2018/07/24 jQuery
Vue 实现拖动滑块验证功能(只有css+js没有后台验证步骤)
2018/08/24 Javascript
python进阶教程之文本文件的读取和写入
2014/08/29 Python
python 网络编程详解及简单实例
2017/04/25 Python
Win7下Python与Tensorflow-CPU版开发环境的安装与配置过程
2018/01/04 Python
基于Python Numpy的数组array和矩阵matrix详解
2018/04/04 Python
Python实现Restful API的例子
2019/08/31 Python
布隆过滤器的概述及Python实现方法
2019/12/08 Python
基于python实现ROC曲线绘制广场解析
2020/06/28 Python
pycharm 添加解释器的方法步骤
2020/08/31 Python
波兰办公用品和学校用品在线商店:Dlabiura24.pl
2020/11/18 全球购物
客服专员岗位职责范本
2013/11/29 职场文书
群众路线批评与自我批评
2014/02/06 职场文书
单位承诺书格式
2014/05/21 职场文书
学生顶撞老师的检讨书
2014/09/17 职场文书
庆祝教师节标语
2014/10/09 职场文书
导师工作推荐信
2015/03/27 职场文书