一、装饰器回顾:

1、标准的装饰器示例

 def trapper(func):
def inner(*args, **kwargs):
print('插入到被装饰函数前的功能!')
res = func(*args, **kwargs)
print('插入到被装饰函数后的功能!')
return res return inner @trapper
def func():
print('this is func!') func()

2、代码运行时间装饰器的优化

考虑如果同时有500个函数要解除检查代码运行时间,会不会费太多时间取注释掉语法糖?
是不是可以用标志控制,只改它就可以关闭或者打开装饰器
 import time
ON_OFF = True # 装饰器控制开关,默认是关的 def count_time(func):
def inner(*args, **kwargs):
global ON_OFF # 如果不能使用该关键字,毕竟不安全
if ON_OFF:
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print('the function run use: %s'%(end - start))
return res
re = func(*args, **kwargs)
return re return inner @count_time
def func_wrapped():
time.sleep(0.233)
print('wrapping me!') @count_time
def woqu():
time.sleep(0.31415926)
print('wo ququququuuuuuuuu') func_wrapped()
woqu()

3、高阶优化代码运行时间装饰器

如果不使用global关键字,在局部域中使用全局变量,毕竟不安全,如何改造?
 ef timmer_out(flag):   # 在装饰器外再加一层函数,传入标志位,函数的最多嵌套三层!
def timmer(func):
def inner(*args, **kwargs):
if ON_OFF:
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print('the function run use: %s' % (end - start))
return res
re = func(*args, **kwargs)
return re return inner
return timmer @timmer_out(ON_OFF) # --> 等同于先执行timmer_out(ON_OFF)函数,返回:timmer;接着执行@timmer语法糖
def func_use_time():
time.sleep(0.233)
print('use ti me!') @timmer_out(ON_OFF)
def func_waste_time():
time.sleep(0.31415926)
print('wo waste') func_use_time()
func_waste_time()

二、@wraps的使用

解决在被装饰函数得不到原本函数名的问题
 print(func.__name__)  # 打印的结果时:inner ,因为被装饰后,func = trapper(func) 即 func = inner
# 如何得到它原本的名字了?
# 引入库
from functools import wraps def a_new_trapper(a_func):
@wraps(a_func)
def wrap_the_function():
print("I am doing some boring work before executing a_func()")
a_func()
print("I am doing some boring work after executing a_func()") return wrap_the_function @a_new_trapper
def a_function_requiring_trapper():
"""Hey yo! Decorate me!"""
print("I am the function which needs some trap to "
"remove my foul smell") print('a_function_requiring_trapper.__name__')
print(a_function_requiring_trapper.__name__)

三、多层装饰器

即多个装饰器同时装饰一个函数;
引入场景:网上购物时登录后,其他操作如:添加商品到购物车,删除购物车中的商品就不用再登录了!
同时登录用户的每个动作都要记录到日志中。
 FLAG = False

 def login(func):
@wraps(func) # 此处也要加,否者写入日志的还是inner
def inner(*args, **kwargs):
global FLAG
while 1:
if FLAG is False:
name = input('请输入您的登录名:')
passwd = input('请输入您的登录密码:')
if name == 'lisi' and passwd == '':
FLAG = True
break
print('您输入的密码或者登录名不正确!请重新输入!')
continue
break
res = func(*args, **kwargs)
return res return inner def log(func):
@wraps(func)
def inner(*args, **kwargs):
res = func(*args, **kwargs)
with open('log', mode='a', encoding='utf-8') as f:
f.write(func.__name__ + '\n')
return res return inner @log
@login
def add_merc_to_cart():
print('I just add some merchandise to the cart!') @log
@login
def del_merc_in_cart():
print('I just del some merchandise in the cart!') add_merc_to_cart()
del_merc_in_cart()
多层装饰器的标准演示流程
 ef wrapper1(func):
def inner(*args, **kwargs):
print('第一个装饰器wrapper1,在函数前的添加!')
res = func(*args, **kwargs)
print('第一个装饰器wrapper1,在函数后的添加!')
return res return inner def wrapper2(func):
def inner2(*args, **kwargs):
print('第二个装饰器wrapper2,在函数前的添加!')
res = func(*args, **kwargs)
print('第二个装饰器wrapper3,在函数后的添加!')
return res return inner2 def wrapper3(func):
def inner3(*args, **kwargs):
print('第三个装饰器wrapper3,在函数前的添加!')
res = func(*args, **kwargs)
print('第三个装饰器wrapper3,在函数后的添加!')
return res return inner3 @wrapper3
@wrapper2
@wrapper1
def wuha():
print('wu haaaaaaaaaaaaaaaaa!') wuha()

Python进阶-IV-Wrapper高阶的更多相关文章

  1. python进阶学习之高阶函数

    高阶函数就是把函数当做参数传递的一种函数, 例如: 执行结果: 1.map()函数 map()接收一个函数 f 和一个list, 并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 l ...

  2. 《前端之路》之 JavaScript 进阶技巧之高阶函数(下)

    目录 第二章 - 03: 前端 进阶技巧之高阶函数 一.防篡改对象 1-1:Configurable 和 Writable 1-2:Enumerable 1-3:get .set 2-1:不可扩展对象 ...

  3. 【python】python函数式编程、高阶函数

    1.map() : python内置的高阶函数,接收一个函数f和一个list,并通过把函数f依次作用在list的每个元素上,得到一个新的list并            返回. def f(x): r ...

  4. python 函数式编程:高阶函数,map/reduce

    python 函数式编程:高阶函数,map/reduce #函数式编程 #函数式编程一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数 #(一)高阶函数 f=abs f print ...

  5. python入门16 递归函数 高阶函数

    递归函数:函数内部调用自身.(要注意跳出条件,否则会死循环) 高阶函数:函数的参数包含函数 递归函数 #coding:utf-8 #/usr/bin/python """ ...

  6. python内置常用高阶函数(列出了5个常用的)

    原文使用的是python2,现修改为python3,全部都实际输出过,可以运行. 引用自:http://www.cnblogs.com/duyaya/p/8562898.html https://bl ...

  7. Python之路 day3 高阶函数

    #!/usr/bin/env python # -*- coding:utf-8 -*- #Author:ersa """ 变量可以指向函数,函数的参数能接收变量, 那么 ...

  8. Python 编程基础之高阶函数篇(一)

      高阶函数:能接受函数作为参数的函数. 如: f=abs def   add(x,y,f): return f(x)+f(y) 如果我们用:add(-5,9,f)来调用该高阶函数,则返回结果为:14 ...

  9. python笔记十三(高阶函数、装饰器)

    一.高阶函数 函数只要有以下两个特征中一个就可以称为高阶函数: a:函数名作为一个实参传入另一个函数中 b:函数的返回值中包含函数名 下面我们用代码来感受一下这两种形式: import time # ...

  10. python高级特性和高阶函数

    python高级特性 1.集合的推导式 列表推导式,使用一句表达式构造一个新列表,可包含过滤.转换等操作. 语法:[exp for item in collection if codition] if ...

随机推荐

  1. FWT-快速沃尔什变换

    FWT-快速沃尔什变换 FWT有啥用啊 我们知道,FFT可以解决多项式的卷积,即 \[ C_k=\sum_{i+j=k}A_i*B_j \] 如果将操作符换一下,换成集合运算符 比如 \[ C_k=\ ...

  2. C# HTTP系列12 以form-data方式上传键值对集合到远程服务器

    系列目录     [已更新最新开发文章,点击查看详细] 使用multipart/form-data方式提交数据与普通的post方式有一定区别.multipart/form-data的请求头必须包含一个 ...

  3. Visual Studio 2019 for Mac 离线更新方法

    当你打开Visual Studio 2019 for Mac检查更新时,如果下载更新包很慢,可以尝试如下操作: 打开Finder(访达),找到~/Library/Caches/VisualStudio ...

  4. iOS依赖库管理工具之CocoaPods

    CocoaPods 是开发 OS X 和 iOS 应用程序的一个第三方库的依赖管理工具.利用 CocoaPods,可以定义自己的依赖关系库 (称作 pods),并且随着时间的变化,在整个开发环境中对第 ...

  5. CentOS7 配置ip地址

    1.查看网络配置文件 可能因为不同的系统,配置文件都不一样,总体来说,配置文件都是 前缀:ifcfg-eno + 后缀:随机数组成 进入到 /etc/sysconfig/network-scripts ...

  6. WCF服务支持HTTP(get,post)

    WCF服务支持HTTP(get,post)方式请求例子   方式一: /// <summary> /// Http Get请求 /// </summary> /// <p ...

  7. Java中Deque特性及API

    美人如斯,文章如斯! 定义 双向队列:支持插入删除元素的线性集合 特性: 插入.删除.获取操作支持两种形式:快速失败和返回null或true/false 既具有FIFO特点又具有LIFO特点,即是队列 ...

  8. 【07】Jenkins:流水线(Pipeline)

    写在前面的话 个人认为 Pipeline 在 Jenkins 中算是一个优化性功能,它能够将我们的构建服务的整个过程流程化,这意味着当我们在执行到某一步的时候,可以添加询问,提示我们是否继续运行下一步 ...

  9. linux 定时器日志操作

    首先先打开定时器的日志(默认是注释掉的) cron的日志功能使用syslogd服务,不同版本号linux可能装了不同的软件,这里介绍常见的两种: rsyslog-> 位置在 /etc/rsysl ...

  10. JAVA中调用外部程序,并等待其退出(涉及Runtime和ProcessBuilder)

    这段时间要写一个java调用外部程序的功能,踩了几个坑,这里分享一下. 首先用的是RunTime,调用代码如下: Process pro = Runtime.getRuntime().exec(&qu ...