一、装饰器回顾:

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. java web开发入门十二(idea创建maven SSM项目需要解决的问题)基于intellig idea(2019-11-09 11:23)

    一.spring mvc action返回string带双引号问题 解决方法: 在springmvc.xml中添加字符串解析器 <!-- 注册string和json解析适配器 --> &l ...

  2. mysql修改windows下的data目录

    在windows下,安装完mysql后,建议把数据目录(data目录)移动到非系统目录,避免系统出问题的时候还原. 1.在d盘创建一个mysqldata 2.给新文件增加权限NetworkServic ...

  3. http与tcp,udp的区别

    1.网络协议的概念 (1)在学习网络课程的时候,老师会讲iso七层模型,有应用层 表示层 会话层 传输层 网络层 数据链路层 物理层,其中http就属于应用层,tcp与udp是属于传输层,如图1.1( ...

  4. centos 安装 oracle11r2

    因为要测试spark链接oracle,所以需要再服务器装oracle 1.下载oracle, 如果自己下载需要注册,比较麻烦,可以直接用如下命令下载 因为zip比较大,建议nohup 后台下载 noh ...

  5. .NET Standard和.NET Core是什么关系(转载)

    .NET Standard vs .NET Core 问: I have read about the difference between .NET Standard and .NET Core, ...

  6. MVC+Ninject+三层架构+代码生成 -- 总结(三、實體類)

    一.動軟代碼生成器生成 實體類 2.VS視圖--實體類,其中Condition文件夾是存放 搜索的分頁信息 using System; using System.Collections.Generic ...

  7. Delphi - 利用TRzTrayIcon实现WinFrm工程最小化到托盘

    第三方RC控件的安装 浏览器搜索Delphi Rz控件下载,找到下载一个安装文件,解压后点击RC3.exe一键安装. Delphi WinFrm工程最小化到托盘 Delphi新建WinFrm工程,在主 ...

  8. Redis基本使用(一)

    redis window系统的redis是微软团队根据官方的linux版本高仿的 官方原版: https://redis.io/ 中文官网:http://www.redis.cn 1 redis下载和 ...

  9. OO第四单元作业小结

    一.本单元两次作业的架构设计 1.第一次作业 整体思路:以class为核心,建立MyInterface.MyAttribute.MyOperation.MyAssociation四个类分别储存每个类的 ...

  10. thinkphp路由配置route.php

    路由设置配置 打开route.php  引入Route控制器类(use think\Route;) 设置路由-->  Route::rule('路由表达式','路由地址','请求类型','路由参 ...