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调用java的Webservice示例
Mar 10 Python
Python中实现两个字典(dict)合并的方法
Sep 23 Python
简单掌握Python中glob模块查找文件路径的用法
Jul 05 Python
python查看微信好友是否删除自己
Dec 19 Python
python 捕获shell脚本的输出结果实例
Jan 04 Python
Python对象类型及其运算方法(详解)
Jul 05 Python
python利用socketserver实现并发套接字功能
Jan 26 Python
python爬虫之urllib3的使用示例
Jul 09 Python
Python3 执行Linux Bash命令的方法
Jul 12 Python
Python3简单爬虫抓取网页图片代码实例
Aug 26 Python
python KNN算法实现鸢尾花数据集分类
Oct 24 Python
Python实现将蓝底照片转化为白底照片功能完整实例
Dec 13 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和js如何通过json互相传递数据相关问题探讨
2013/02/26 PHP
PHP分页类集锦
2014/11/18 PHP
javascript 写类方式之三
2009/07/05 Javascript
jquery加载页面的方法(页面加载完成就执行)
2011/06/21 Javascript
js+JQuery返回顶部功能如何实现
2012/12/03 Javascript
简约JS日历控件 实例代码
2013/07/12 Javascript
javascript dom追加内容实现示例
2013/09/21 Javascript
jQuery的Scrollify插件实现滑动到页面下一节点
2015/07/05 Javascript
JS实现仿新浪黄色经典滑动门效果代码
2015/09/27 Javascript
javascript下拉列表菜单的实现方法
2015/11/18 Javascript
AngularJS中监视Scope变量以及外部调用Scope方法
2016/01/23 Javascript
Jquery和JS获取ul中li标签的实现方法
2016/06/02 Javascript
AngularJs expression详解及简单示例
2016/09/01 Javascript
微信小程序 在Chrome浏览器上运行以及WebStorm的使用
2016/09/27 Javascript
微信小程序 slider的简单实例
2017/04/19 Javascript
通过js修改input、select默认字体颜色
2017/04/19 Javascript
基于bootstrap页面渲染的问题解决方法
2018/08/09 Javascript
Vue  webpack 项目自动打包压缩成zip文件的方法
2019/07/24 Javascript
d3.js实现图形拖拽
2019/12/19 Javascript
Angular8 实现table表格表头固定效果
2020/01/03 Javascript
[02:57]DOTA2亚洲邀请赛小组赛第四日 赛事回顾
2015/02/02 DOTA
Python读取mp3中ID3信息的方法
2015/03/05 Python
Python下线程之间的共享和释放示例
2015/05/04 Python
详解Python中的type()方法的使用
2015/05/21 Python
使用Python & Flask 实现RESTful Web API的实例
2017/09/19 Python
Python探索之实现一个简单的HTTP服务器
2017/10/28 Python
使用Python防止SQL注入攻击的实现示例
2020/05/21 Python
Python语言编写智力问答小游戏功能
2020/10/13 Python
HTML5 video 上传预览图片视频如何设置、预览视频某秒的海报帧
2018/08/28 HTML / CSS
SheIn俄罗斯:时尚女装网上商店
2017/02/28 全球购物
德国传统玻璃制造商:Cristalica
2018/04/23 全球购物
研究生毕业鉴定
2014/01/29 职场文书
中学生家长评语大全
2014/04/16 职场文书
工作简历的自我评价
2019/05/16 职场文书
详解MySql中InnoDB存储引擎中的各种锁
2022/02/12 MySQL
海康机器人重磅发布全新算法开发平台VM4.2
2022/04/21 数码科技