欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

python—装饰器

发布时间:2025/3/11 python 33 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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—装饰器的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。