python—装饰器
装饰器概念:
把一个函数当作参数传递给一个函数,返回一个替代版的函数
本质上就是一个返回函数的函数
在不改变原函数的基础上,给函数增加功能
python 中装饰器做的事情!它们封装一个函数,并且用这样或者那样的方式来修改它的行为
@ 符号,那只是一个简短的方式来生成一个被装饰的函数
def outer(func):def inner():print('*****')func()return inner@outer
def func():print('have a nice day!')
@outer
def func2():print('hello world')
func()
func2()运行结果:
*****
have a nice day!
*****
hello world
装饰器示例:
import time# 装饰器
def decorator(func):def wrapper():print(time.time())func()return wrapper@decorator # 调用装饰器
def f1():print('This is a function...')def f2(): # 没有装饰器print('This is a function...')f1()
f2()运行结果:
1560391414.8582878 f1
This is a function...
This is a function... f2
装饰器实现一个函数计时器
import time
import string
import random
import functoolsli = [random.choice(string.ascii_letters)for i in range(1000)]def timeit(fun):# 问题1:被装饰的函数有返回值的时候怎么办?# 问题2:被装饰的函数如何保留自己的函数名和帮助信息文档?@functools.wraps(fun)def wapper(*args, **kwargs):"""这是一个wapper函数"""# 在函数的执行之前start_time = time.time()# 执行函数res = fun(*args, **kwargs)# 在函数执行之后end_time = time.time()print('运行的时间为:%.6f' % (end_time - start_time))return resreturn wapper@timeit
def con_add():s = ''for i in li:s += (i + '+')print(s)@timeit
def join_add():print('+'.join(li))con_add()
join_add()@timeit
def fun_list(n):"""这是fun_list函数,被timeit装饰"""return [2 * i for i in range(n)]
@timeit
def fun_map(n):"""这是fun_map函数,被timeit装饰"""return list(map(lambda x:x*2,range(n)))# fun_list(5000)
# fun_map(5000)
print(fun_list.__doc__)
print(fun_map.__doc__)
print(fun_list.__name__)
print(fun_map.__name__)
创建装饰器, 要求如下:
1 . 创建add_log装饰器, 被装饰的函数打印日志信息;
2 . 日志格式为: [字符串时间] 函数名: xxx,
运行时间:xxx, 运行返回值结果:xxx
import time
import functools
print(time.ctime())def add_log(func):@functools.wraps(func)def wrapper(*args,**kwargs):start_time = time.time()res = func(*args,**kwargs)end_time = time.time()print('[%s] 函数名:%s,运行时间:%.6f,运行返回值的''结果:%d' %(time.ctime(),func.__name__,end_time-start_time,res))return resreturn wrapper
@add_log
def add(x,y):time.sleep(1)return x+y
add(1,10)
多个装饰器装饰函数,从上到下执行
def decorator_a(fun):def inner_a(*args,**kwargs):print('Get in inner_a')return fun(*args,**kwargs)return inner_adef decorator_b(fun):def inner_b(*args,**kwargs):print('Get in inner_b')return fun(*args,**kwargs)return inner_b@decorator_b
@decorator_a
def f(x):print('Gat in f')return x*2f(1)
多个装饰器的应用场景:
会采用多个装饰器先验证是否登陆成功,再验证登陆权限是否足够
inspect.getcallargs会返回一个字典,
import inspect
import functools
def is_admin(fun):@functools.wraps(fun)def wrapper(*args,**kwargs):# inspect.getcallargs 会返回一个字典,# key值:形参 value:对应的实参数inspect_res = inspect.getcallargs(fun,*args,**kwargs)print('inspect的返回值是:%s' %(inspect_res))if inspect_res.get('name') == 'root':temp = fun(*args,**kwargs)return tempelse:print('not root user,no permisson add user')return wrapper
login_session = ['root','admin','redhat']def is_login(fun):@functools.wraps(fun)def wrapper(*args,**kwargs):if args[0] in login_session:temp = fun(*args,**kwargs)return tempelse:print('Error:%s 没有登陆成功' %(args[0]))return wrapper
@is_login
@is_admin
def add_user(name):print('add user~')
add_user('root')
代参数的装饰器
import functools
import timedef log(kind):def add_log(func):@functools.wraps(func)def wrapper(*args,**kwargs):start_time = time.time()res = func(*args,**kwargs)end_time = time.time()print('<%s>[%s] 函数名:%s,运行时间:%.6f,运行返回值的''结果:%d' %(kind,time.ctime(),func.__name__,end_time-start_time,res))return resreturn wrapperreturn add_log
@log('debug')
def add(x,y):time.sleep(1)return x+y
print(add(1,2))
练习题:
编写装饰器required_types, 条件如下:
1). 当装饰器为@required_types(int,float)确保函数接收到的每一个参数都是int或者float类型;
2). 当装饰器为@required_types(list)确保函数接收到的每一个参数都是list类型;
3). 当装饰器为@required_types(str,int)确保函数接收到的每一个参数都是str或者int类型;
4). 如果参数不满足条件, 打印 TypeError:参数必须为xxxx类型
import functools
def required_types(*kinds):def required_int(fun):@functools.wraps(fun)def wrapper(*args, **kwargs):for i in args:if not isinstance(i, kinds):# print('TypeError:参数必须为',kinds)# breakraise TypeError('参数必须为%s,%s' % kinds)else:res = fun(*args, **kwargs)return resreturn wrapperreturn required_int# @required_types(float, float)
# def add(a, b):
# return a + b
#
# print(add(1.1, 2.0))
运行结果为:3.1# @required_types(list)
# def add(a, b):
# return a + b
#
# print(add(1.1, 2.0))
运行结果为:
Traceback (most recent call last):File "/home/kiosk/PycharmProjects/20190523/练习.py", line 65, in <module>print(add(1.1, 2.0))File "/home/kiosk/PycharmProjects/20190523/练习.py", line 42, in wrapperraise TypeError('参数必须为%s,%s' % kinds)
TypeError: not enough arguments for format string
python—装饰器相关推荐
- python简单装饰器_简单介绍Python装饰器(一)
装饰器的作用 相信大家在 探索过程中已经了解装饰器的作用,也有很多花里胡哨的介绍. 这次小冰也来讲解一下关于Python装饰器的一些小知识. 它的作用: 性能测试 日志 安全验证 ...... 相信大 ...
- Python装饰器的神奇功能:自动打印每个方法耗时
问题: 运行代码时,尤其对于大型项目需要分析每个环节方法耗时的.每个方法前后都写计算耗时及日志打印太繁琐了,而且代码不精简. 解决: Python装饰器类似于Spring的 AOP(Aspect Or ...
- python装饰器教学_Python装饰器学习(九步入门)
这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 # -*- coding:gbk -*- '''示例1: 最简单的函数,表示调用了两次 ...
- 简单介绍python装饰器
这篇文章简单介绍一下python装饰器,希望对你们有所帮助. 简单正常python例子: def up(text):return text.upper() #转成大写 def lo(text):ret ...
- Python装饰器是什么?使用Python装饰器实现计算程序(函数)运行时间的功能
Python装饰器是什么?使用Python装饰器实现计算程序(函数)运行时间的功能 目录
- python 装饰器示例
python 装饰器示例 import timedef decorator(func): # 传函数def wrapper(*args, **kwargs): # 传参数(也可以传固定参数)start ...
- [转]python 装饰器
以前你有没有这样一段经历:很久之前你写过一个函数,现在你突然有了个想法就是你想看看,以前那个函数在你数据集上的运行时间是多少,这时候你可以修改之前代码为它加上计时的功能,但是这样的话是不是还要大体读读 ...
- python装饰器与闭包_Python 装饰器和闭包
Python 装饰器和闭包 装饰器是 Python 中常见的语法糖,这篇文章讲了闭包和装饰器的原理,并且分析了函数中变量的作用域,以及尝试总结了常见的坑. 装饰器基础 首先来看看装饰器的定义:装饰器本 ...
- 利用世界杯,读懂 Python 装饰器
Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性, 熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic. 今天就结合最近的世界杯带大家理解下装饰器. 德 ...
- Python 装饰器记录总结 (终极版)
Python 装饰器记录总结 (终极版) 原文链接:http://magicroc.com/2017/04/10/Python装饰器记录总结/ 装饰器是一个函数,一个用来包装函数的函数,装饰器在函数申 ...
最新文章
- 千亿级照片,毫秒间匹配最佳结果,微软开源Bing搜索背后的关键算法
- 数组 ——求出一组数的最大值(用数组实现)
- 2020 中国技术力量年度榜单
- debian9 配置ssh 允许 root直接远程登录
- 任何一台计算机都可以安装win 7系统,最全面win7系统如何安装
- LoadRunner使用odbc时报错can't get hostname for your address的解决方法
- Vue打包并发布项目
- 跨平台 webapp 开发技术之 Hybrid App
- JavaScript内置的Math对象(附实例)
- 谷歌卫星地图下载助手
- 前端面试宝典总结(一)(搬自牛客)
- 匹配滤波器的仿真——线性调频信号
- MATLAB使用cic滤波器,基于Matlab的CIC滤波器设计
- vue 项目上传视频到保利威
- Poker Ⅱ 机械键盘使用说明书 自备
- jest中的mock,jest.fn()、jest.spyOn()、jest.mock()
- 小程序 - 微信授权登录 微信授权绑定手机号
- (小)算法题(长期更新)
- 【报告分享】百度创新营销资源整合方案(2021)-百度营销研究院(附下载)
- 稳健经营,龙光集团成为“中国地产上市公司财务稳健奖”获得者之一
热门文章
- java异常标记_java.lang.RuntimeException:错误:0D0680A8:asn1编码例程:ASN1_CHECK_TLEN:错误的标记...
- pyspark sparksession_PySpark 处理数据和数据建模
- 野火stm32呼吸灯程序_说一说STM32启动过程
- 魅族android 版本 6.0下载,flyme6.0内测版
- h5微信本地调试 vue_vueh5中使用微信sdk
- php yii2 sns,GitHub - yggphpcoder/iisns: 基于 yii2 的 sns 社区系统,一站式解决社区建站...
- sed教程入门与实例练习(一)
- 中缀表达式转换成后缀表达式(只适用于加减乘除运算)
- 10.8-全栈Java笔记:序列化/反序列化的步骤和实例
- JavaScript中的arguments对象