python编写装饰器_我也来写一下python装饰器

有借用,但原文出处已经找不到了,根据笔记分享一下解释器的基础。

下面的代码表示,等待两秒钟,输出‘test is running'。

现在要求增加统计程序运行时间的功能。

等待两秒钟,输出‘test is running',现要求增加统计程序运行时间的功能。

import time

def test():

time.sleep(2)

print('test is running!')

test()

学习先问为什么,有什么用,学基础的时候有时不理解为什么简单的事情要搞那么复杂,而对应的实际应用时,往往“这个复杂方法有很多优点和简化了很多事情”。学基础时用简单的例子,只是为了讲明知识点,而不要去关注例子实现的什么功能,这个功能当然是个‘屁’了。

那么,装饰器的实际应用场景:程序已上线或已使用,但需要增加新功能,修改原函数不合理也不科学(这里真的包含了很多背景声音),就要求:

(1)不能修改原功能函数的代码。例子中的功能是非常简单的,要实现当然是直接修改,但现实中一个功能的实现是非常复杂的代码,直接修改是不合理不科学的。

(2)不能修改原函数的调用方式。在符合第一条的情况下,调用时仍然是用test(),即老方法能实现新功能。现实中后面程序在反复用test(),就是要完全不动老代码的基础上,增加一个’装饰器‘更新整个程序。

(3)上述说的老方法是表面上的,这就是装饰器介入的作用。

好,以下开始改造,用试错的方法解释装饰器的实现过程和原理。

满足条件(1)可以增加代码如下:

def deco(func):

start=time.time()

func()

stop=time.time()

print(stop-start)

deco(test)

#把老代码里的test函数作为参数传递给新函数

#(因为是增加新功能,老功能还是要的,所以新代码里肯定要引用老代码的功能,就采取了这种方法)

看上去新功能就实现了,但可以看到调用方式变为了deco(test),即违背了条件(2),以前程序里可能反复调用了test(),都要改成deco(test),不科学。

同时满足条件(2),再改:

思路:产生一个新函数,重新赋值给test,test=某函数,那么后面反复调用的test()就被实质上改过来了,实现功能。

#试一下:

test=deco(test) #计算右边的,是一个两行字符串,赋值给test根本不是一个函数。

test() #因此跳错误码

再试一下:

增加:return func

然后:

test=deco(test)

test()

代码正常运行,但因为return func的缩进和其他代码是同级的,所以deco(test)这步已经把新功能给实现了,又返回了一次test(),结果重复。

把下面完整的代码去试一下,出现了两次test is running ,不合格。

import time

def test():

time.sleep(2)

print('test is running!')

def deco(func):

start=time.time()

func()

stop=time.time()

print(stop-start)

return func

test=deco(test)

test()

思路没有错,上述这里return一个函数的思考过程也是对的,只是返回的方式不对,应当使用’嵌套函数‘。

def timer(func):

def deco():

start=time.time()

func()

stop=time.time()

print(stop-start)

return deco

#把deco()嵌套在timer(func)里,返回一个deco()函数的函数名deco;

#调用timer(func)时,deco()里面的过程代码类似于没有执行的,

#被打包成了一个函数,执行的只是return了这个函数的函数名。

test=timer(test)

#右边代码返回的是一个deco()的函数名deco,deco()打包了作为被参数传入的原test()里的功能,

#同时增加了新功能。

test()

#符合(2)要求,没有改变调用方法,但实质上这句调用的已经是deco()了。

#顶格代码是不能调用经过了二次缩进的嵌套函数的,

#但这里用了deco()用了return,成了闭包函数,就可以被调用了。

至此,本质上是修改了调用函数,但在表面上并未修改调用方式,而且实现了附加功能,需求实现。

真正的装饰器:语法糖

在原test()的上一行加上@timer,删除test=timer(test).

而且要把新增的函数写在原函数的上面

最后代码

import time

def timer(func):

print(func.__name__) #看看打印出来的是什么

def deco():

start=time.time()

func()

stop=time.time()

print(stop-start)

return deco

@timer

def test():

time.sleep(2)

print('test is running')

#test=timer(test)这句不用了,注释掉

test()

过程比较啰嗦,但每一步都看下来后,装饰 器的原理就知道了,涉及到有参数的时候,再另外理解了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/455289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VirtualBox安装Centos6.8出现——E_INVALIDARG (0x80070057)

VirtualBox使用已有的虚拟硬盘出错: 问题描述:UUID已经存在 Cannot register the hard disk E:\system_iso\centos6.8.vdi {05f096aa-67fc-4191-983d-1ed00fc6cce9} because a hard disk E:\system_iso\centos68_02\centos6.8.vdi with UUID {05f096aa-6…

DFT 与 ATPG综 述

DFT 可测试性设计 工程会接触 DFT。需要了解 DFT 知识,但不需要深入。 三种基本的测试(概念来自参考文档): 边界扫描测试:Boundary Scan Test: 测试目标是 IO-PAD,利用 JTAG 接口互连以方便 测试。&#x…

非线性动力学_非线性动力学特辑 低维到高维的联通者

序言: 本文将以维度为主线, 带量大家进入非线性动力学的世界。 文章数学部分不需要全部理解, 理解思维方法为主非线性动力学,是物理学的思维进入传统方法所不能解决的问题的一座丰碑。它可以帮助我们理解不同复杂度和时间空间尺度…

Go语言channel与select原理

本文会尝试解释 go runtime 中 channel 和 select 的具体实现,部分内容来自 gophercon2017。Go版本为1.8.3channel 第一部分讲述一下 channel 的用法。channel 可以看做一个队列,用于多个goroutine之间的通信,例如下面的例子,一个…

Xadmin添加用户小组件出错

环境: Python 3.5.6 Django 2.1 Xadmin 原因: render函数在django2.1上有变化 解决方案: 1.在Python终端输入命令help(xadmin) 查看xadmin安装位置 得到如下输出 FILE/root/anaconda3/envs/learndjango/lib/python3.5/site-packages/xad…

成本预算的四个步骤_全网推广步骤有哪些?

全网推广的步骤是什么?一般来说,搜索引擎优化是大多数中小企业常用的推广方法。主要是通过对一些搜索引擎的排名来提高网站的曝光率,从而更好的提高自己网站的流量,从而更好的实现互联网层面的销售。接下来,让我们学习…

undefined reference to `std::cout'等错误

(1)gcc和g都是GNU(组织)的一个编译器。 (2)后缀名为.c的程序和.cpp的程序g都会当成是c的源程序来处理。而gcc不然,gcc会把.c的程序处理成c程序。 (3)对于.cpp的程序,编译可以用gcc/g…

FFPLAY的原理(二)

关于包Packets的注释从技术上讲一个包可以包含部分或者其它的数据,但是ffmpeg的解释器保证了我们得到的包Packets包含的要么是完整的要么是多种完整的帧。现在我们需要做的是让SaveFrame函数能把RGB信息定稿到一个PPM格式的文件中。我们将生成一个简单的PPM格式文件…

python生成requirements.txt的两种方法

python项目如何在另一个环境上重新构建项目所需要的运行环境依赖包? 使用的时候边记载是个很麻烦的事情,总会出现遗漏的包的问题,这个时候手动安装也很麻烦,不能确定代码报错的需要安装的包是什么版本。这些问题,requi…

node.js 安装使用http-server

node.js npm全局安装了http-server后我该怎么使用它?我在它的安装目录下创建了inde.html,浏览器localhost:8080可以访问,那我的项目需要放在它的安装目录下?还是需要在我的项目下配置什么或者使用什么指令启动它?我在我…

D - 卿学姐与魔法

卿学姐与魔法 Time Limit: 1200/800MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit Status“你的膜法也救不了你 在去拯救公主的道路上,卿学姐披荆斩棘,刀刃早已锈迹斑斑。 一日卿学姐正在为武器的问题发愁,碰到了正…

python对excel表统计视频教程_Python实现对excel文件列表值进行统计的方法

本文实例讲述了Python实现对excel文件列表值进行统计的方法。分享给大家供大家参考。具体如下:#!/usr/bin/env python#codinggbk#此PY用来统计一个execl文件中的特定一列的值的分类import win32com.clientfilenameraw_input("请输入要统计文件的详细地址&#…

mooc后台管理系统设计

摘 要 本设计采用Python中的Django框架实现Mooc后台管理界面设计,django是一个完整的开源web开源框架,使用起来能够快速的搭建你想要的网站,由于django自带后台管理系统,本设计中后台管理模板采用功能更加强大的Xadmin实现。数据库部分采用mysql5.7,由于django中有自带封装的数…

DirectShow系统初级指南

流媒体的处理,以其复杂性和技术性,一向广受工业界的关注。特别伴随着因特网的普及,流媒体在网络上的广泛应用,怎样使流媒体的处理变得简单而富有成效逐渐成为了焦点问题。选择一种合适的应用方案,事半功倍。此时&#…

正则正整数含0

^0?$|^([1-9][0-9]*)?$

MySQL 数据库导出导入操作

有时需要将 MySQL 数据库中的数据导入到其它的数据库中,这里以从 Ubuntu 系统的 MySQL 数据库导出 zabbix 这个数据库到 Windows 系统中的MySQL 为例。 导出数据库 导出数据其实非常方便,比如将 MySQL 中的 zabbix 这个数据库导出到当前文件夹&#xff…

您的apple id 暂时不符合使用此应用程序_Mac相机不工作时该怎么办

苹果公司的许多台式机和笔记本电脑都包含一个内置网络摄像头,该公司愉快地将其称为FaceTime相机。但是,如果您的Mac网络摄像头无法正常工作,并且在尝试访问它时显示为断开连接或不可用,则您可能不会感到高兴。您可以尝试以下操作来…

基于DirectShow的流媒体解码和回放

一、 前言  流媒体的定义很广泛,大多数时候指的是把连续的影像和声音信息经过压缩处理后放上网站服务器,让用户一边下载一边观看、收听,而不需要等整个压缩文件下载到自己机器就可以观看的视频/音频传输、压缩技术。流媒体也指代由这种技术…

《知易行难》扩展练习

在学习了《知易行难》后,这个是一个选做的扩展练习,但是里面的问题真的的很好,所以我也将在这里真实的分享,但是有些敏感的人名我就隐去了。 1. 这一年你做了些什么事情? 1)团队的整合,将团队…

python 裁判文书网_python - 用selenium模拟登陆裁判文书网,系统报错找不到元素。...

问 题from selenium import webdriverfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilitiesdcap dict(DesiredCapabilities.PHANTOMJS)dcap["phantomjs.page.settings.userAgent"]("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWeb…