装饰器概念:
把一个函数当作参数传递给一个函数,返回一个替代版的函数
本质上就是一个返回函数的函数
在不改变原函数的基础上,给函数增加功能
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—装饰器相关推荐

  1. python简单装饰器_简单介绍Python装饰器(一)

    装饰器的作用 相信大家在 探索过程中已经了解装饰器的作用,也有很多花里胡哨的介绍. 这次小冰也来讲解一下关于Python装饰器的一些小知识. 它的作用: 性能测试 日志 安全验证 ...... 相信大 ...

  2. Python装饰器的神奇功能:自动打印每个方法耗时

    问题: 运行代码时,尤其对于大型项目需要分析每个环节方法耗时的.每个方法前后都写计算耗时及日志打印太繁琐了,而且代码不精简. 解决: Python装饰器类似于Spring的 AOP(Aspect Or ...

  3. python装饰器教学_Python装饰器学习(九步入门)

    这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 # -*- coding:gbk -*- '''示例1: 最简单的函数,表示调用了两次 ...

  4. 简单介绍python装饰器

    这篇文章简单介绍一下python装饰器,希望对你们有所帮助. 简单正常python例子: def up(text):return text.upper() #转成大写 def lo(text):ret ...

  5. Python装饰器是什么?使用Python装饰器实现计算程序(函数)运行时间的功能

    Python装饰器是什么?使用Python装饰器实现计算程序(函数)运行时间的功能 目录

  6. python 装饰器示例

    python 装饰器示例 import timedef decorator(func): # 传函数def wrapper(*args, **kwargs): # 传参数(也可以传固定参数)start ...

  7. [转]python 装饰器

    以前你有没有这样一段经历:很久之前你写过一个函数,现在你突然有了个想法就是你想看看,以前那个函数在你数据集上的运行时间是多少,这时候你可以修改之前代码为它加上计时的功能,但是这样的话是不是还要大体读读 ...

  8. python装饰器与闭包_Python 装饰器和闭包

    Python 装饰器和闭包 装饰器是 Python 中常见的语法糖,这篇文章讲了闭包和装饰器的原理,并且分析了函数中变量的作用域,以及尝试总结了常见的坑. 装饰器基础 首先来看看装饰器的定义:装饰器本 ...

  9. 利用世界杯,读懂 Python 装饰器

    Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性, 熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic. 今天就结合最近的世界杯带大家理解下装饰器. 德 ...

  10. Python 装饰器记录总结 (终极版)

    Python 装饰器记录总结 (终极版) 原文链接:http://magicroc.com/2017/04/10/Python装饰器记录总结/ 装饰器是一个函数,一个用来包装函数的函数,装饰器在函数申 ...

最新文章

  1. 千亿级照片,毫秒间匹配最佳结果,微软开源Bing搜索背后的关键算法
  2. 数组 ——求出一组数的最大值(用数组实现)
  3. 2020 中国技术力量年度榜单
  4. debian9 配置ssh 允许 root直接远程登录
  5. 任何一台计算机都可以安装win 7系统,最全面win7系统如何安装
  6. LoadRunner使用odbc时报错can't get hostname for your address的解决方法
  7. Vue打包并发布项目
  8. 跨平台 webapp 开发技术之 Hybrid App
  9. JavaScript内置的Math对象(附实例)
  10. 谷歌卫星地图下载助手
  11. 前端面试宝典总结(一)(搬自牛客)
  12. 匹配滤波器的仿真——线性调频信号
  13. MATLAB使用cic滤波器,基于Matlab的CIC滤波器设计
  14. vue 项目上传视频到保利威
  15. Poker Ⅱ 机械键盘使用说明书 自备
  16. jest中的mock,jest.fn()、jest.spyOn()、jest.mock()
  17. 小程序 - 微信授权登录 微信授权绑定手机号
  18. (小)算法题(长期更新)
  19. 【报告分享】百度创新营销资源整合方案(2021)-百度营销研究院(附下载)
  20. 稳健经营,龙光集团成为“中国地产上市公司财务稳健奖”获得者之一

热门文章

  1. java异常标记_java.lang.RuntimeException:错误:0D0680A8:asn1编码例程:ASN1_CHECK_TLEN:错误的标记...
  2. pyspark sparksession_PySpark 处理数据和数据建模
  3. 野火stm32呼吸灯程序_说一说STM32启动过程
  4. 魅族android 版本 6.0下载,flyme6.0内测版
  5. h5微信本地调试 vue_vueh5中使用微信sdk
  6. php yii2 sns,GitHub - yggphpcoder/iisns: 基于 yii2 的 sns 社区系统,一站式解决社区建站...
  7. sed教程入门与实例练习(一)
  8. 中缀表达式转换成后缀表达式(只适用于加减乘除运算)
  9. 10.8-全栈Java笔记:序列化/反序列化的步骤和实例
  10. JavaScript中的arguments对象