侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

Python  /  管理员 发布于 7年前   151

本文实例讲述了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@timmerdef 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解释器如何回收变量:采用引用计数。当引用有没有了时(门牌号不存在),变量就被回收了。

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

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

函数调用顺序:其他的高级语言类似,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无顺序之分

原理图为:

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 timedef 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 timedef bar():   time.sleep(3)   print("in the bar")def test3(func):  print(func)  return funcbar = 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 timeruser,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 wrapperdef index():  print("welcome to index page!")@authdef home():  print("welcome to index home!")  return "from home"@authdef 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 timeruser,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_wrapperdef 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()

运行结果:

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

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


  • 上一条:
    python如何制作缩略图
    下一条:
    11个Python Pandas小技巧让你的工作更高效(附代码实例)
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客