装饰器就是一个闭包,它的主要作用是在不改变原函数的基础上对原函数功能进行扩展。

我们先来写一个简单的函数:

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学习笔记(十三):装饰器的更多相关文章

  1. Python学习笔记:装饰器

    Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...

  2. Python学习笔记012——装饰器

    1 装饰器 1.1装饰器定义 在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 1.2 装饰器分类 装饰器:函数装饰器,类装饰器,函数的装饰器,类的装饰器 装饰器:函数装饰函 ...

  3. python学习笔记之装饰器、递归、算法(第四天)

    参考老师的博客: 金角:http://www.cnblogs.com/alex3714/articles/5161349.html 银角:http://www.cnblogs.com/wupeiqi/ ...

  4. python学习笔记:装饰器2

    python的装饰器本质是函数,为了不改变装饰目标函数内部代码而增加额外功能而存在 一.一般装饰函数实例: import datetime def func_name(func):#定义一个装饰函数, ...

  5. Python学习笔记之装饰器原理

    def decorator(fn): def wrapper(): print("询价") fn() print("购买成功!") return wrapper ...

  6. python学习笔记(五):装饰器、生成器、内置函数、json

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...

  7. python学习笔记之装饰器、生成器、内置函数、json(五)

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里面 ...

  8. Python3学习笔记十三

    1.   css 老师的博客:http://www.cnblogs.com/yuanchenqi/articles/6856399.html 选择器:找到想要改变的标签 css的功能:渲染和布局 2. ...

  9. Python3学习笔记15-迭代器与生成器

    生成器 如果创建一个有很多元素的列表,但是只需要访问前几个元素,后面的元素占着的空间就白白浪费了 在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间. 在Pytho ...

  10. python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息,抓取政府网新闻内容

    python3.4学习笔记(十三) 网络爬虫实例代码,使用pyspider抓取多牛投资吧里面的文章信息PySpider:一个国人编写的强大的网络爬虫系统并带有强大的WebUI,采用Python语言编写 ...

随机推荐

  1. orzdba工具配置

    ./orzdba -lazy -rt -S /u01/svr/working/my3306/run/mysql.sock mysql -s --skip-column-names -h127.0.0. ...

  2. c语言:<tchar.h>

    头文件“<tchar.h>”作用就是为了进行ASCII码和UNICODE(wide-character)码的头文件(该头文件由微软提供): 这样我们就可以使用TCHAR.H头文件中的定义的 ...

  3. redis 学习(6)-- 集合类型

    redis 学习(6)-- 集合类型 set 结构 无序 无重复 集合间操作 set 集合内操作 命令 含义 sadd key memebr1 [member2...] 向集合中添加一个或多个成员 s ...

  4. qt webengineview 设置背景颜色

    当使用qwebengineview加载网页的使用,可以通过网页端的css设置网页的显示效果 但是当窗口大小改变的时候,你会发现网页的resize速度赶不上窗口的resize速度,这是会出现白色空白,而 ...

  5. 关于Linux防火墙的问题以及关闭,试一下这四条命令

    关闭防火墙,依次执行以下四条命令 临时服务 service firewalld stop 永久关闭 chkconfig iptables off 列出所有规则 iptables -L 清除所有规则,可 ...

  6. 利用mybatis-generator自动生成代码(转)

    利用mybatis-generator自动生成代码 mybatis-generator有三种用法:命令行.eclipse插件.maven插件.个人觉得maven插件最方便,可以在eclipse/int ...

  7. mysql alter 语句用法,添加、修改、删除字段、索引、主键等

    修改表名: ALTER  TABLE admin_user RENAME TO a_use //增加主键 [sql] view plaincopy alter table tabelname add  ...

  8. 韦东山嵌入式Linux学习笔记05--存储管理器

    SDRAM: 原理图如下:          jz2440 v3开发板上面用的内存芯片为钰创科技公司生产的EM63A165TS,一片内存大小为32MB大小,一共有两块,共64MB的大小. SDRAM接 ...

  9. traceback:让你更加灵活地处理python的异常

    异常 异常在python中是屡见不鲜了,程序在执行到某一行代码时,发现有问题,比如数组索引越界,变量没有定义啊等等,此时就会抛出异常 捕获异常 在python,一般都是使用try···except来对 ...

  10. QT5.9 QString和字符串转换的乱码问题

    QString转字符串的乱码: 先在头文件加入: //解决QString到char的中文乱码 #if _MSC_VER >= 1600 #pragma execution_character_s ...