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学习之编写查询ip程序
Feb 27 Python
Python文件与文件夹常见基本操作总结
Sep 19 Python
Python win32com 操作Exce的l简单方法(必看)
May 25 Python
django传值给模板, 再用JS接收并进行操作的实例
May 28 Python
Python实现的各种常见分布算法示例
Dec 13 Python
Python列表删除元素del、pop()和remove()的区别小结
Sep 11 Python
python3 实现函数写文件路径的正确方法
Nov 27 Python
pytorch中图像的数据格式实例
Feb 11 Python
基于Python的自媒体小助手---登录页面的实现代码
Jun 29 Python
python中绕过反爬虫的方法总结
Nov 25 Python
Python常用断言函数实例汇总
Nov 30 Python
关于pytest结合csv模块实现csv格式的数据驱动问题
May 30 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
利用文件属性结合Session实现在线人数统计
2006/10/09 PHP
分享下页面关键字抓取www.icbase.com站点代码(带asp.net参数的)
2014/01/30 PHP
学习php设计模式 php实现策略模式(strategy)
2015/12/07 PHP
php获取POST数据的三种方法实例详解
2016/12/20 PHP
Django中的cookie与session操作实例代码
2017/08/17 PHP
JS JavaScript获取Url参数,src属性参数
2021/03/09 Javascript
基于jquery的多彩百分比 动态进度条 投票效果显示效果实现代码
2011/08/28 Javascript
jQuery 拖动层(在可视区域范围内)
2012/05/24 Javascript
jQuery怎么解析Json字符串(Json格式/Json对象)
2013/08/09 Javascript
jsPDF导出pdf示例
2014/05/02 Javascript
详解JavaScript中Date.UTC()方法的使用
2015/06/12 Javascript
通过设置CSS中的position属性来固定层的位置
2015/12/14 Javascript
AngularJS自定义指令之复制指令实现方法
2017/05/18 Javascript
使用nvm管理不同版本的node与npm的方法
2017/10/31 Javascript
nodejs+mongodb aggregate级联查询操作示例
2018/03/17 NodeJs
微信小程序事件对象中e.target和e.currentTarget的区别详解
2019/05/08 Javascript
python抓取京东价格分析京东商品价格走势
2014/01/09 Python
python生成随机验证码(中文验证码)示例
2014/04/03 Python
Python的Flask框架的简介和安装方法
2015/11/13 Python
python实现决策树ID3算法的示例代码
2018/05/30 Python
python 2.7.13 安装配置方法图文教程
2018/09/18 Python
200行python代码实现2048游戏
2019/07/17 Python
Python 类属性与实例属性,类对象与实例对象用法分析
2019/09/20 Python
Python使用微信接入图灵机器人过程解析
2019/11/04 Python
使用pyhon绘图比较两个手机屏幕大小(实例代码)
2020/01/03 Python
总结30个CSS3选择器
2017/04/13 HTML / CSS
Html5页面上如何禁止手机虚拟键盘弹出
2020/03/19 HTML / CSS
皮姆斯勒语言学习:Pimsleur Language Programs
2018/06/30 全球购物
泰国的头号网上婴儿用品店:Motherhood.co.th
2019/04/09 全球购物
介绍下static、final、abstract区别
2015/01/30 面试题
小学生期末自我鉴定
2014/01/19 职场文书
会计与出纳自荐书范文
2014/03/16 职场文书
雷锋精神演讲稿
2014/05/13 职场文书
消防演习感想
2015/08/10 职场文书
小学班主任工作经验交流材料
2015/11/02 职场文书
python 如何执行控制台命令与操作剪切板
2021/05/20 Python