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语言编写 ...
随机推荐
- [BZOJ2594] [WC2006]水管局长(Kruskal+LCT)
[BZOJ2594] [WC2006]水管局长(Kruskal+LCT) 题面 SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可 ...
- Python 入门 之 初识面向对象
Python 入门 之 初识面向对象 1.初识面向对象编程 (核心--对象) (1)观察以下代码: # 面向过程编程 s = "alexdsb" count = 0 for i i ...
- 如何决定使用 HashMap 还是 TreeMap? (转)
问:如何决定使用 HashMap 还是 TreeMap? 介绍 TreeMap<K,V>的Key值是要求实现java.lang.Comparable,所以迭代的时候TreeMap默认是按照 ...
- Java设计模式七种写法
懒汉模式-线程不安全 public class Singleton { private static Singleton instance; private Singleton (){ } publi ...
- 分布式唯一ID生成器Twitter
分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有些时候我们希望能使用一种简单一 ...
- Codeforces 1196D2. RGB Substring (hard version)
传送门 考虑枚举每一个位置作为可能子段的起点,然后对以这个位置为起点的所有情况下的答案取 $min$ 当固定了起点 $i$ 并且固定了起点 $i$ 最终的字符时,答案也固定了 发现对于所有与 $i \ ...
- Wizard's Tour CodeForces - 860D (图,构造)
大意: 给定$n$节点$m$条边无向图, 不保证连通, 求选出最多邻接边, 每条边最多选一次. 上界为$\lfloor\frac{m}{2}\rfloor$, $dfs$贪心划分显然可以达到上界. # ...
- debezium关于cdc的使用(下)
博文原址:debezium关于cdc的使用(下) 简介 debezium在debezium关于cdc的使用(上)中有做介绍.具体可以跳到上文查看.本篇主要讲述使用kafka connector方式来同 ...
- Eclipse安装Hadoop插件配置Hadoop开发环境
一.编译Hadoop插件 首先需要编译Hadoop 插件:hadoop-eclipse-plugin-2.6.0.jar,然后才可以安装使用. 第三方的编译教程:https://github.com/ ...
- jumpserver开源堡垒机部署安装
0x01.前言 Jumpserver 是全球首款完全开源的堡垒机,使用 GNU GPL v2.0 开源协议,是符合 4A 的专业运维审计系统. Jumpserver 使用 Python / Djang ...