1. 带参数的装饰器
应用场景:
在使用装饰器对原函数进行装饰后,可以控制装饰器什么生效,什么时候不生效
即在想使用原函数时,不需要对语法糖进行注释,或者删除装饰器
以下使用一个例子进行说明:
import time
# 定义Flag标志位,当为真的时候,装饰器生效,否则装饰器不生效
FALG = False
def timmer_out(flag):
def timmer(func):
def inner(*args, **kwargs):
if flag:
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(end-start)
return res
else:
res = func(*args, **kwargs)
return res
return inner
return timmer
"""
@timmer_out(FALG)
等价于:
timmer = timmer_out(Flag)
@timmer
@timmer_out(FLAG):
先执行timmer_out(FALG),将FLAG标志位的值传递进函数中,返回内部函数timmer的引用,
再@timmer执行此语法糖:func = timmer(func) == inner
FALG标志位:
当FLAG=True,则装饰器生效,执行if语句块;
当FLAG=False,则执行else语句块内容,也就是func原函数,此时装饰器不生效
使用此方法,当使用装饰器装饰了多个函数后,若想恢复原函数的功能,
则更改FLAG的值即可,不需要对装饰器或者语法糖进行修改
"""
@timmer_out(FALG)
def func1():
time.sleep(0.1)
print('this is function 1')
@timmer_out(FALG)
def func2():
time.sleep(0.1)
print('this is function 2')
print('FALG的值 :', FALG)
func1()
func2()
当FALG=False时,装饰器失效,仅执行原函数的功能:
当FALG=True时,装饰器生效,执行结果:
2.多个装饰器装饰同一个函数
使用下面例子来进行说明:
def wrapper1(func):
print('---in wrapper11---')
def inner1():
print('---in inner11---')
func()
print('---in inner12---')
print('---in wrapper12---')
return inner1
def wrapper2(func):
print('---in wrapper21---')
def inner2():
print('---in inner21---')
func()
print('---in inner22---')
print('---in wrapper22---')
return inner2
@wrapper2
@wrapper1
def f():
print('---in f---')
f()
执行顺序如下:
运行结果如下(重点在于内部函数的执行规律):
对于装饰器的执行原则:就近原则,因此先进入wrapper1内执行
对于装饰器内函数的执行 :就远原则,先执行wrapper2内函数inner2()
在使用多个装饰器装饰同一个函数时,注意执行顺序
3. 查看函数名与函数的注释
需要引入新的模块: functools
- 基础查看
def func_test():
'''
一个用来测试的函数
:return: None
'''
print('测试函数')
#查看字符串格式的函数名
print(func_test.__name__)
# 查看此函数的注释
print(func_test.__doc__)
输出结果:
但是,当想获取一个被装饰函数的信息时:
def wrapper(fun):
def inner(*args, **kwargs):
'''
:param args: inner参数
:param kwargs: inner参数
:return: inner
'''
res = fun(*args, **kwargs)
return res
return inner
@wrapper
def func(a,b):
return a,b
res = func(111,222)
print(func.__name__)
print(func.__doc__)
我们可以看到,此时只能获取装饰器内函数的信息:
想要获取被装饰函数的信息,需要使用functools模块:
from functools import wraps
def wrapper(fun):
@wraps(fun)
def inner(*args, **kwargs):
res = fun(*args, **kwargs)
return res
return inner
@wrapper
def func(a,b):
'''这是被装饰函数func'''
# print('Hello Python',a,b)
return a,b
res = func(111,222)
print('函数名: ',func.__name__)
print('函数注释: ',func.__doc__)
执行结果如下:
4. 补充
urllib是python自带的模块
from urllib.request import urlopen
# 拿到网页的源代码
def get_url():
url = 'https://www.baidu.com'
def get():
res = urlopen(url).read()
print(res)
return get
get_func = get_url()
# 在每次执行get_func时不需要再重新定义url并开辟空间
get_func()