Python3.5装饰器原理及应用实例详解


Posted in Python onApril 30, 2019

本文实例讲述了Python3.5装饰器原理及应用。分享给大家供大家参考,具体如下:

1、装饰器:

(1)本质:装饰器的本质是函数,其基本语法都是用关键字def去定义的。

(2)功能:装饰其他函数,即:为其他函数添加附加功能

(3)原则:不能修改被装饰的函数的源代码,不能修改被装饰的函数的调用方式。即:装饰器对待被修饰的函数是完全透明的。

(4)简单应用:统计函数运行时间的装饰器

import time
#统计函数运行时间的砖装饰器
def timmer(func):
  def warpper(*args,**kwargs):
    strat_time = time.time()
    func()
    stop_time = time.time()
    print("the func run time is %s" %(stop_time-strat_time))
  return warpper
@timmer
def test1():
  time.sleep(3)
  print("in the test1")
test1()

运行结果:

in the test1
the func run time is 3.000171661376953

(5)实现装饰器知识储备:

a、函数即“变量”

b、高阶函数

c、函数嵌套

d、高阶函数+嵌套函数==》装饰器

2、装饰器知识储备——函数即“变量”

定义一个函数,相当于把函数体赋值给这个函数名。

Python解释器如何回收变量:采用引用计数。当引用有没有了时(门牌号不存在),变量就被回收了。

函数的定义也有内存回收机制,与变量回收机制一样。匿名函数没有函数名,就会被回收。

Python3.5装饰器原理及应用实例详解

变量的使用:先定义再调用,只要在调用之前已经存在(定义)即可;函数即“变量”,函数的使用是一样的。

函数调用顺序:其他的高级语言类似,Python 不允许在函数未声明之前,对其进行引用或者调用

下面的两段代码运行效果一样:

def bar():
  print("in the bar")
def foo():
  print("in the foo")
  bar()
foo()
#python为解释执行,函数foo在调用前已经声明了bar和foo,所以bar和foo无顺序之分
def foo():
  print("in the foo")
  bar()
def bar():
  print("in the bar")
foo()

运行结果:

in the foo
in the bar
in the foo
in the bar

注意:python为解释执行,函数foo在调用前已经声明了bar和foo,所以bar和foo无顺序之分

原理图为:

Python3.5装饰器原理及应用实例详解

3、装饰器知识储备——高阶函数

满足下列其中一种即可称之为高阶函数:

a、把一个函数名当做实参传递给另一个函数(在不修改被装饰函数的情况下为其添加附加功能)

b、返回值中包含函数名(不修改函数的调用方式)

(1)高阶函数示例:

def bar():
  print("in the bar")
def test1(func):
  print(func)  #打印门牌号,即内存地址
  func()
test1(bar)   #门牌号func=bar

运行结果:

<function bar at 0x00BCDFA8>
in the bar

(2)高阶函数的妙处——把一个函数名当做实参传递给另一个函数(在不修改被装饰函数的情况下为其添加附加功能)

import time
def bar():
  time.sleep(3)
  print("in the bar")
#test2在不修改被修饰函数bar的代码时添加了附加的及时功能
def test2(func):
  start_time = time.time()
  func()   #run bar
  stop_time = time.time()
  print("the func run time is %s " %(stop_time-start_time))
#调用方式发生改变,不能像原来的方法去调用被修饰的函数(所以不能实现装饰器的功能)
test2(bar)
#bar()

运行结果:

in the bar
the func run time is 3.000171661376953

(3)高阶函数的妙处——返回值中包含函数名(不修改函数的调用方式)

import time
def bar():
   time.sleep(3)
   print("in the bar")
def test3(func):
  print(func)
  return func
bar = test3(bar)
bar()  #run bar

运行结果:

<function bar at 0x00BADFA8>
in the bar

4、装饰器知识储备——嵌套函数

#函数嵌套
def foo():
  print("in the foo")
  def bar():  #bar函数具有局部变量的特性,不能在外部调用,只能在内部调用
    print("in the bar")
  bar()
foo()

运行结果:

in the foo
in the bar

装饰器应用——模拟网站登录页面,访问需要认证登录页面

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#模拟网站,访问页面和部分需要登录的页面
import timer
user,passwd = "liu","liu123"
def auth(func):
  def wrapper(*args,**kwargs):
    username = input("Username:").strip()
    password = input("Password:").strip()
    if username == user and password == passwd:
      print("\033[32;1mUser has passed authentication!\033[0m")
      res = func(*args,**kwargs)
      print("-----after authentication---")
      return res
    else:
      exit("\033[31;1mInvalid username or password!\033[0m")
  return wrapper
def index():
  print("welcome to index page!")
@auth
def home():
  print("welcome to index home!")
  return "from home"
@auth
def bbs():
  print("welcome to index bbs!")
#函数调用
index()
print(home())
bbs()

运行结果:

welcome to index page!
Username:liu
Password:liu123
User has passed authentication!
welcome to home page!
-----after authentication---
from home
Username:liu
Password:liu123
User has passed authentication!
welcome to bbs page!
-----after authentication---

装饰器带参数

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#模拟网站,访问页面和部分需要登录的页面,多种认证方式
import timer
user,passwd = "liu","liu123"
def auth(auth_type):
  print("auth func:",auth_type)
  def outer_wrapper(func):
    def wrapper(*args, **kwargs):
      print("wrapper func args:",*args, **kwargs)
      if auth_type == "local":
        username = input("Username:").strip()
        password = input("Password:").strip()
        if username == user and password == passwd:
          print("\033[32;1mUser has passed authentication!\033[0m")
          #被装饰的函数中有返回值,装饰器中传入的参数函数要有返回值
          res = func(*args, **kwargs)  #from home
          print("-----after authentication---")
          return res
        else:
          exit("\033[31;1mInvalid username or password!\033[0m")
      elif auth_type == "ldap":
        print("ldap....")
    return wrapper
  return outer_wrapper
def index():
  print("welcome to index page!")
@auth(auth_type="local")    #利用本地登录 home = wrapper()
def home():
  print("welcome to home page!")
  return "from home"
@auth(auth_type="ldap")    #利用远程的ldap登录
def bbs():
  print("welcome to bbs page!")
#函数调用
index()
print(home())   #wrapper()
bbs()

运行结果:

Python3.5装饰器原理及应用实例详解

更多关于Python相关内容可查看本站专题:《Python数据结构与算法教程》、《Python Socket编程技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》及《Python入门与进阶经典教程》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python getopt模块处理命令行选项实例
May 13 Python
Python中函数参数设置及使用的学习笔记
May 03 Python
python学习开发mock接口
Apr 28 Python
python+webdriver自动化环境搭建步骤详解
Jun 03 Python
Python OpenCV 调用摄像头并截图保存功能的实现代码
Jul 02 Python
详细介绍Python进度条tqdm的使用
Jul 31 Python
PyCharm导入python项目并配置虚拟环境的教程详解
Oct 13 Python
Python selenium页面加载慢超时的解决方案
Mar 18 Python
Keras 切换后端方式(Theano和TensorFlow)
Jun 19 Python
python修改微信和支付宝步数的示例代码
Oct 12 Python
Django rest framework如何自定义用户表
Jun 09 Python
关于python类SortedList详解
Sep 04 Python
11个Python Pandas小技巧让你的工作更高效(附代码实例)
Apr 30 #Python
python制作图片缩略图
Apr 30 #Python
python获取微信企业号打卡数据并生成windows计划任务
Apr 30 #Python
使用Python实现企业微信的自动打卡功能
Apr 30 #Python
Python/Django后端使用PIL Image生成头像缩略图
Apr 30 #Python
Python3.5迭代器与生成器用法实例分析
Apr 30 #Python
python使用Paramiko模块实现远程文件拷贝
Apr 30 #Python
You might like
PHP 翻页 实例代码
2009/08/07 PHP
PHP定时任务延缓执行的实现
2014/10/08 PHP
php自动加载方式集合
2016/04/04 PHP
php实现数组重复数字统计实例
2018/09/30 PHP
PHP将英文数字转换为阿拉伯数字实例讲解
2019/01/28 PHP
php常用的工具开发整理
2019/09/26 PHP
PHP并发场景的三种解决方案代码实例
2021/02/27 PHP
jQuery示例收集
2010/11/05 Javascript
JavaScript学习小结(一)——JavaScript入门基础
2015/09/02 Javascript
BootStrap表单验证实例代码
2017/01/13 Javascript
完美实现js焦点轮播效果(一)
2017/03/07 Javascript
JavaScript实现的反序列化json字符串操作示例
2018/07/18 Javascript
小结Python用fork来创建子进程注意事项
2014/07/03 Python
python通过BF算法实现关键词匹配的方法
2015/03/13 Python
Python采用Django制作简易的知乎日报API
2016/08/03 Python
caffe binaryproto 与 npy相互转换的实例讲解
2018/07/09 Python
python实现的MySQL增删改查操作实例小结
2018/12/19 Python
Python3中_(下划线)和__(双下划线)的用途和区别
2019/04/26 Python
如何通过雪花算法用Python实现一个简单的发号器
2019/07/03 Python
python try except返回异常的信息字符串代码实例
2019/08/15 Python
Python数据可视化:泊松分布详解
2019/12/07 Python
BeautifulSoup中find和find_all的使用详解
2020/12/07 Python
HTML5 Canvas自定义圆角矩形与虚线示例代码
2013/08/02 HTML / CSS
HearthSong官网:儿童户外玩具、儿童益智玩具
2017/10/16 全球购物
Pat McGrath Labs官网:世界上最有影响力的化妆师推出的彩妆品牌
2018/01/07 全球购物
圣彼得堡鲜花配送:Semicvetic
2020/09/15 全球购物
Servlet如何得到服务器的信息
2015/12/22 面试题
毕业生造价工程师求职信
2013/10/17 职场文书
面包店的创业计划书范文
2014/01/16 职场文书
旅游市场营销方案
2014/03/09 职场文书
大学生工作自荐书
2014/06/16 职场文书
大专应届毕业生求职信
2014/07/15 职场文书
结婚当天新郎保证书
2015/05/08 职场文书
2015年法律事务部工作总结
2015/07/27 职场文书
2016年度师德标兵先进事迹材料
2016/02/26 职场文书
mysql查询结果实现多列拼接查询
2022/04/03 MySQL