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的Pyspider为例剖析搜索引擎的网络爬虫实现方法
Mar 30 Python
简单说明Python中的装饰器的用法
Apr 24 Python
Python虚拟环境Virtualenv使用教程
May 18 Python
python计算一个序列的平均值的方法
Jul 11 Python
Python对象类型及其运算方法(详解)
Jul 05 Python
利用python批量修改word文件名的方法示例
Oct 17 Python
Django外键(ForeignKey)操作以及related_name的作用详解
Jul 29 Python
python网络编程 使用UDP、TCP协议收发信息详解
Aug 29 Python
python os.path.isfile 的使用误区详解
Nov 29 Python
基于python图像处理API的使用示例
Apr 03 Python
Django中的模型类设计及展示示例详解
May 29 Python
Python批量修改xml的坐标值全部转为整数的实例代码
Nov 26 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
paypal即时到账php实现代码
2010/11/28 PHP
PHP循环语句笔记(foreach,list)
2011/11/29 PHP
Laravel实现用户注册和登录
2015/01/23 PHP
初识ThinkPHP控制器
2016/04/07 PHP
Laravel实现定时任务的示例代码
2017/08/10 PHP
页面只有一个text的时候,回车自动submit的解决方法
2010/08/12 Javascript
使用CSS样式position:fixed水平滚动的方法
2014/02/19 Javascript
jQuery使用prepend()方法在元素前添加内容用法实例
2015/03/26 Javascript
JQuery入门基础小实例(1)
2015/09/17 Javascript
使用jQuery制作浮动工具栏的实例分享
2016/05/13 Javascript
Web前端新人笔记之jquery入门心得(新手必看)
2016/05/17 Javascript
详解jQuery中关于Ajax的几个常用的函数
2017/07/17 jQuery
vue 打包后的文件部署到express服务器上的方法
2017/08/09 Javascript
js Dom实现换肤效果
2017/10/21 Javascript
JS+WCF实现进度条实时监测数据加载量的方法详解
2017/12/19 Javascript
详解webpack模块加载器兼打包工具
2018/09/11 Javascript
解决layui table表单提示数据接口请求异常的问题
2019/09/24 Javascript
详解ES6数组方法find()、findIndex()的总结
2020/05/12 Javascript
[01:36:57]【09DOTA2第一视角】小骷髅
2014/04/16 DOTA
[47:52]完美世界DOTA2联赛PWL S2 PXG vs InkIce 第二场 11.26
2020/11/30 DOTA
python使用arp欺骗伪造网关的方法
2015/04/24 Python
python套接字流重定向实例汇总
2016/03/03 Python
python DataFrame获取行数、列数、索引及第几行第几列的值方法
2018/04/08 Python
pycharm配置git(图文教程)
2019/08/16 Python
python函数enumerate,operator和Counter使用技巧实例小结
2020/02/22 Python
Python绘制动态水球图过程详解
2020/06/03 Python
使用豆瓣源来安装python中的第三方库方法
2021/01/26 Python
纯CSS3单页切换导航菜单界面设计的简单实现
2016/08/16 HTML / CSS
html5组织文档结构_动力节点Java学院整理
2017/07/11 HTML / CSS
护理专业个人求职简历的自我评价
2013/10/13 职场文书
中式结婚主持词
2014/03/14 职场文书
仓库管理员岗位职责
2014/03/19 职场文书
个人综合鉴定材料
2014/05/23 职场文书
小学班级口号
2014/06/09 职场文书
跟班学习心得体会(共6篇)
2016/01/23 职场文书
Python中tqdm的使用和例子
2022/09/23 Python