1.装饰器:
含义:把一个函数当作参数,返回一个替代版的函数,本质就是一个返回函数的函数
在不改变原函数的基础上,给函数增加功能
--------(1)题目要求:
举例说明装饰器的用法(此程序在生活中并不适用,仅限于说明装饰器的作用)
-------->代码如下:
def func1():
print('~~~~~~')
print('Hello world')
def outer():
func1()
print('~~~~~~~~~~~')
func1()
a = outer()
-------->结果如下:
-------->(2)题目要求:
举例说明装器的使用
主要思路:
装饰器首先执行login()函数,发现安有装饰器,就先执行装饰器,执行装饰器时先跳过,看到返回一个函数,故执行此函数,接着返回login函数,执行此函数
-------->代码如下:
def desc(fun):
def add_info():
print('清明节快乐~')
fun()
return add_info
@desc
def login():
# print('清明节快乐~')
print('login...')
@desc
def logout():
print('logout...')
login()
logout()
-------->结果如下:
装饰器:对修改是封闭的,对扩展是开放的
------->(3)题目要求(装饰器的介绍):
举例说明装饰器的作用
------->代码如下:
方法一:
import time
def f1():
print('This is a function...')
print(time.time()) #从1970年1月1日零点零分到现在一共多少秒
f1()
方法二:
import time
def f1():
print('This is a function...')
def f2():
print('This is a function...')
#从1970年1月1日零点零分到现在一共多少秒
def print_currenttime(func):
print(time.time())
func()
print_currenttime(f1)
print_currenttime(f2)
方法三:
import time
#只执行了装饰器
def decorator(func): ##函数为参数,闭包
def wrapper(): ##真正的功能函数
print(time.time())
func() ##看给谁加这个功能
return wrapper
def f1(): ##当作参数传到函数中
print('This is a function ...')
def f2(): ##当作参数传到函数中
print('This is a function ...')
f=decorator(f1)
f()
方法四:
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()
------->结果如下:
------->(4)题目要求(可变参数的装饰器):
举例说明如何使用可变参数的装使器
------->代码如下:
import time
def decorator(func):
def wrapper(*args):
print(time.time())
func(*args)
return wrapper
@decorator
def f1(func_name):
print('This is a function ' + func_name)
@decorator
def f2(func_name1,func_name2):
print('This is a function ' + func_name1)
print('This is a function ' + func_name2)
f1('test')
f2('test1','test2')
------->结果如下:
------->(5)题目要求:
举例说明如何使用关键字参数的装使器
------->代码如下:
import time
def decorator(func):
def warpper(*args,**kwargs):
print(time.time())
func(*args,**kwargs)
return warpper
@decorator
def f1(func_name):
print('This is a function ' + func_name)
@decorator
def f2(func_name1,func_name2):
print('This is a function ' + func_name1)
print('This is a function ' + func_name2)
@decorator
def f3(func_name1,func_name2,**kwargs):
print('This is a function ' + func_name1)
print('This is a function ' + func_name2)
print(kwargs)
f1('test')
f2('test1','test2')
f3('test1','test2',a=1,b=2,c='westos')
------->结果如下:
2.装饰器练习:
装饰器练习(一)(有返回值)
------->题目要求:
装饰器实现一个函数计时器(在函数执行之前之后都打印一次时间)
------->代码如下:
import time
import random
import string
import functools ##导入帮助文档
li = [random.choice(string.ascii_letters) for i in range(10)]
print(li)
def decorator(func):
@functools.wraps(func) #打印原来函数的帮助文档,如果去掉后,便打印的是现在函数的帮助文档
def wrapper(*args,**kwargs):
"""这是一个装饰器"""
start_time=time.time()
res=func(*args,**kwargs)
end_time=time.time()
print('运行的时间为%f' %(end_time-start_time))
return res
return wrapper
#计算两者的时间的长短
@decorator
def con_add():
s = ''
for i in li:
s += (i + ',')
print(s)
@decorator
def join_add():
print(','.join(li))
con_add()
join_add()
# 计算两者的时间的长短
@decorator
def fun_list(n):
"""这是一个fun_list函数"""
#print([i * 2 for i in range(n)])
return [i * 2 for i in range(n)]
@decorator
def fun_map(n):
#print(list(map(lambda x: x * 2, range(n))))
return list(map(lambda x: x * 2, range(n)))
print(fun_list(5))
print(fun_map(5))
print(fun_list.__doc__)
print(fun_list.__name__)
print(time.ctime()) #什么时间运行的函数
------->结果如下:
分析:
1.string.ascii_letters中的内容是:‘z-Z,-9’
2.choice是选择其中的一个
3.被装饰的函数有返回值
装饰器练习(二)
------->题目要求:
装饰器实现一个函数计时器
1.可能会出现的问题1:被装饰的函数有返回值
2.可能会出现的问题2:如何保留被装饰函数的函数名和帮助信息文档
------->代码如下:
import time
import random
import string
import functools
li = [random.choice(string.ascii_letters) for i in range(100)]
print(li)
def Timer(fun):
"""这是一个装饰器Timer"""
# @functools.wraps(fun)
def wrapper(*args,**kwargs):
"""这是一个wrapper函数"""
start_time = time.time()
res = fun(*args,**kwargs)
end_time = time.time()
print('运行时间为: %.5f' %(end_time - start_time))
return res
return wrapper
@Timer
def con_add():
s = ''
for i in li:
s += (i + ',')
print(s)
@Timer
def join_add():
print(','.join(li))
@Timer
def fun_list(n):
"""这是fun_list函数"""
return [i * 2 for i in range(n)]
@Timer
def fun_map(n):
return list(map(lambda x:x*2,range(n)))
# con_add()
# join_add()
# print(fun_list(100))
# print(fun_map(100))
print(fun_list.__doc__)
print(fun_list.__name__)
print(time.ctime())
------->结果如下:
装饰器练习(三):
------->题目要求:
尝试得到装饰器中的一些信息,里iru装饰器中的函数名和运行时间,运行返回值结果等
------->代码如下:
import time
import functools
def add_log(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
start_time = time.time()
res = fun(*args,**kwargs)
end_time = time.time()
print('[%s] 函数名: %s, 运行时间: %6f,运行返回值结果: %d' %(time.ctime(),fun.__name__,end_time - start_time,res))
return res
return wrapper
@add_log
def add(x,y):
time.sleep(1)
return x + y
add(1,2)
------->结果如下:
装饰器练习(四)
------->题目要求:
定义装饰器,判断用户登陆时出现的情况
------->代码如下:
import functools
import inspect
def is_admin(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
#inspect.getcallargs返回一个字典,key值是形参,value值
#是对应的实参{'name':'root'}
inspect_res = inspect.getcallargs(fun,*args,*kwargs)
print('inspect的返回值: %s' %inspect_res)
if inspect_res.get('name') == 'root':
res = fun(*args,**kwargs)
return res
else:
print('not root user!')
return wrapper
@is_admin
def add_user(name):
print('添加用户信息...')
def del_user(name):
print('删除用户信息...')
add_user('root')
------->结果如下:
装饰器练习(五)
------->题目要求:
编写装饰器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)
# break #不会影响结果,但是最后输出
raise TypeError('参数必须为%s,%s' %kinds) #抛出异常,如果出错了,会报错
else:
res=fun(*args,**kwargs)
return res
return wrapper
return required_int
@required_types(float,float)
def add(a,b):
return a+b
print(add(1.4,2.8))
------->结果如下:
3.多个装饰器:
------->(1)题目要求:
举例说明多个装饰器如何使用
------->代码如下:
def decorator_a(fun):
print('Get in decorator_a')
def inner_a(*args, **kwargs):
print('Get in inner_a')
res = fun(*args, **kwargs)
return res
return inner_a
def decorator_b(fun):
print('Get in decorator_b')
def inner_b(*args, **kwargs):
print('Get in inner_b')
res = fun(*args, **kwargs)
return res
return inner_b
@decorator_a
@decorator_b
def f(x):
print('Get in f')
return x * 2
f(2)
------->结果如下:
------->(2)题目要求:
多个装饰器练习:
------->代码如下:
import functools
import inspect
def is_admin(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
#inspect.getcallargs返回一个字典,key值是形参,value值
#是对应的实参{'name':'root'}
inspect_res = inspect.getcallargs(fun,*args,*kwargs)
print('inspect的返回值: %s' %inspect_res)
if inspect_res.get('name') == 'root':
res = fun(*args,**kwargs)
return res
else:
print('not root user!')
return wrapper
login_session = ['root', 'redhat', 'westos']
def is_login(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
if args[0] in login_session:
res = fun(*args,**kwargs)
return res
else:
print('Error:%s未登录' %args[0])
return wrapper
@is_login
@is_admin
def add_student(name):
print('添加学生信息...')
add_student('linux')
------->结果如下: