装饰器: 把一个函数当作参数传递给另一个函数 返回一个替代版的函数 本质上就是一个返回函数的函数 在不改变原函数的基础上 给函数增加功能
函数可以作为参数被传递
"""
# def say_hello(name):
# return f"Hello {name}"
# def be_some(name):
# return f"Your {name}"
#
# def greet_bob(func):
# return func("Bob")
#
# print(greet_bob(say_hello))
# print(greet_bob(be_some))
# def say():
# # print('*********')
# print('hello')
# def hello():
# print('!!!!!!!!!!!!!!hello')
def fun(f):
def inner():
print('*********')
f()
print('############')
return inner
@fun #语法糖
def hello():
print('!!!!!!!!!!!!!!hello')
# say()
# say = fun(say)
# print(say)
# say()
# hello = fun(hello)
# hello()
def outer(f):
def inner(age):
if age <=0:
age = 0
f(age)
return inner
@outer
def say(age):
print('year old:',age)
say(-1)
say(-10)
装饰器实现一个函数计时器 1.被装饰的函数有返回值怎么办 2.如何保留被装饰函数的函数名和帮助信息文档
import time
import random
import string
import functools
li = [random.choice(string.ascii_letters) for i in range(100)]
def timeit(func):
@functools.wraps(func)
def wrapper(*args, **kwargs): # 接收可变参数 和关键字参数
"""这是一个装饰器timeit"""
# 在函数运行只前
start_time = time.time()
# 执行函数
res = func(*args, **kwargs)
# 在函数运行之后
end_time = time.time()
print('运行时间为:%.6f' % (end_time - start_time))
return res
return wrapper
@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函数"""
return [2 * i for i in range(n)]
@timeit
def fun_map(n):
"""这是fun_map函数"""
return list(map(lambda x:x*2,range(n)))
# fun_list(100000)
# fun_map(100000)
print(fun_map.__doc__)
print(fun_list.__doc__)
print(fun_map.__name__)
print(fun_list.__name__)
# 创建装饰器, 要求如下: # 1. 创建add_log装饰器, 被装饰的函数打印日志信息; # 2. 日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返回值结果:xxx
import time
import functools
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 res
return wrapper
@add_log
def add(x,y):
time.sleep(1)
return x+y
add(1,10)
编写装饰器required_ints, 条件如下: 1). 确保函数接收到的每一个参数都是整数; 2). 如果参数不是整形数, 打印 TypeError:参数必须为整形
import functools
def required_ints(func):
@functools.wraps(func)
def wrapper(*args,**kwargs): # (1,2,....)
for i in args:
# if isinstance(i,int):
# pass
# else:
# print('函数所有的参数并非全是int型')
if not isinstance(i,int):
print('函数所有的参数并非都是int型')
break
else:
res = func(*args,**kwargs)
return res
return wrapper
@required_ints
def add(a,b):
return a+b
@required_ints
def mymax(a,b,c,d):
return max(a,b,c,d)
print(add(1,2.0))
编写带参数的装饰器
import time
import functools
def 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 res
return wrapper
return add_log
@log('debug')
def add(x,y):
time.sleep(1)
return x+y
add(1,10)
编写装饰器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_type(*kind):
def require(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
for i in args:
if not isinstance(i,kind):
print('函数所有的参数并非',kind)
break
else:
res = fun(*args,**kwargs)
return res
return wrapper
return require
# a = 1.0
# print(isinstance(a,(int,float)))
@required_type(int,float)
def add(a,b):
return a+b
print(add(1,1.2))