Python3学习笔记(十三):装饰器
装饰器就是一个闭包,它的主要作用是在不改变原函数的基础上对原函数功能进行扩展。
我们先来写一个简单的函数:
from time import sleep def foo():
print("Hello World!")
sleep(2)
现在我们要对这个函数加一些功能,比如说打印这个函数的执行时间
有人说,这还不简单啊,直接修改foo函数呢,确实,这是最简单的一种方法。但是在我们实际工作中,有时候是不能对调用的函数进行修改的,那该怎么办呢?
我们可以重新写个打印时间的函数去调用foo函数啊,比如:
import time
from time import sleep def foo():
print("Hello World!")
sleep(2) def show_time(func):
start_time = time.time()
func()
end_time = time.time()
print(end_time - start_time)
调用:
show_time(foo) # 输出:
Hello World!
2.0000178813934326
很好,确实是在不修改foo函数的基础上实现了需求,但是。。。。。有个大问题,改变了函数的调用方式,前面是调用foo()的,现在需要修改成调用show_time()。
看来这种方法也不行。
这个时候就是闭包大展身手的机会了
import time
from time import sleep def foo():
print("Hello World!")
sleep(2) def show_time(func):
def inner():
start_time = time.time()
func()
end_time = time.time()
print(end_time - start_time)
return inner # 调用
foo = show_time(foo)
foo() # 输出
Hello World!
2.000027656555176
到这里已经完美地实现了我们的需求,这就是装饰器。装饰器有个高大上的写法,就是装饰器符号@
上面的代码我们修改成用装饰器符号@来写:
import time
from time import sleep def show_time(func):
def inner():
start_time = time.time()
func()
end_time = time.time()
print(end_time - start_time)
return inner @show_time # 其实就相当于foo = show_time(foo)
def foo():
print("Hello World!")
sleep(2) # 调用
foo()
@show_time的作用就是执行foo()时,跳转到去执行inner(),如下图:

被装饰函数的参数
如果被装饰的函数有形参,那么在装饰器函数中该怎么写呢?
import time
from time import sleep def show_time(func):
def inner(*x):
start_time = time.time()
func(*x)
end_time = time.time()
print(end_time - start_time)
return inner @show_time
def add(*args):
sum = 0
for arg in args:
sum += arg
print(sum)
sleep(2) add(3, 5)
装饰器函数参数
有些时候我们可能需要对不同的被装饰函数加些不同的功能,比如需要对某些函数加上日志打印,那该怎么做呢?
import time
from time import sleep def logger(flag="false"):
def show_time(func):
def inner(*x):
start_time = time.time()
func(*x)
end_time = time.time()
print(end_time - start_time)
if flag == "true":
print("打印日志记录")
return inner
return show_time @logger("true") # 打印日志记录
def add(*args):
sum = 0
for arg in args:
sum += arg
print(sum)
sleep(2) @logger() # 不需要打印日志记录
def foo():
print("Hello World!")
sleep(2)
Python3学习笔记(十三):装饰器的更多相关文章
- Python学习笔记:装饰器
Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...
- Python学习笔记012——装饰器
1 装饰器 1.1装饰器定义 在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 1.2 装饰器分类 装饰器:函数装饰器,类装饰器,函数的装饰器,类的装饰器 装饰器:函数装饰函 ...
- python学习笔记之装饰器、递归、算法(第四天)
参考老师的博客: 金角:http://www.cnblogs.com/alex3714/articles/5161349.html 银角:http://www.cnblogs.com/wupeiqi/ ...
- python学习笔记:装饰器2
python的装饰器本质是函数,为了不改变装饰目标函数内部代码而增加额外功能而存在 一.一般装饰函数实例: import datetime def func_name(func):#定义一个装饰函数, ...
- Python学习笔记之装饰器原理
def decorator(fn): def wrapper(): print("询价") fn() print("购买成功!") return wrapper ...
- python学习笔记(五):装饰器、生成器、内置函数、json
一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...
- python学习笔记之装饰器、生成器、内置函数、json(五)
一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里面 ...
- Python3学习笔记十三
1. css 老师的博客:http://www.cnblogs.com/yuanchenqi/articles/6856399.html 选择器:找到想要改变的标签 css的功能:渲染和布局 2. ...
- Python3学习笔记15-迭代器与生成器
生成器 如果创建一个有很多元素的列表,但是只需要访问前几个元素,后面的元素占着的空间就白白浪费了 在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间. 在Pytho ...
- python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容
python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...
随机推荐
- IDEA Git回退到指定历史版本
1.找到要回退的版本号(右击项目--> Git --> Show History -->选中要回退的版本-->Copy Revision Number): 2.打开idea的T ...
- go build命令详解
原文地址讲解:https://blog.csdn.net/zl1zl2zl3/article/details/83374131
- 安装docker私有仓库
先安装docker:http://www.cnblogs.com/cjsblogs/p/8717304.html 安装私有仓库 #下载registry docker pull registry #制作 ...
- Codeforces 1190C. Tokitsukaze and Duel
传送门 注意到后手可以模仿先手的操作,那么如果一回合之内没法决定胜负则一定 $\text{once again!}$ 考虑如何判断一回合内能否决定胜负 首先如果最左边和最右的 $0$ 或 $1$ 距离 ...
- 什么是 Serverless 应用引擎?优势有哪些?
Serverless 应用引擎(Serverless App Engine,简称 SAE)是面向应用的 Serverless PaaS 平台,能够帮助 PaaS 层用户免运维 IaaS,按需使用,按量 ...
- js里生成guid
function guid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { | , ...
- JS基础_字面量和变量
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- nodejs---crypto模块MD5签名
1.MD5是一种常用的哈希算法,用于给任意数据一个“签名”.这个签名通常用一个十六进制的字符串表示: /*md5签名*/ /*引入crypto模块*/ const crypto = require(' ...
- se37 函数中的异常使用
一种是rase <exceptions> FUNCTION ztest. *"-------------------------------------------------- ...
- kubeadm安装k8s1.13
1.环境介绍: centos 7.4.1708 关闭selinux和iptable,环境很重要! 主机 ip地址 cpu核数 内存 swap host解析 k8s-master 10.0.0.11 2 ...