1. 装饰器
-
什么是装饰器: 它本质就是一个闭包函数,不改变已有函数的代码 对函数添加额外功能 -
注意:
- 已有函数的源代码 和 调用方式 不改动
- 对已有函数增加其它功能
-
开放封闭原则 开放封闭原则,也适用于函数式编程 封闭:对于已经完成的代码块,不修改源代码 开放:对扩展开放,有其它需求是可以 添加
2. 我的第一个装饰器
def fun_outer(func):
def fun_inner():
func()
print('这是我添加的额外功能')
return fun_inner
def comment():
print('这是我的已有函数!')
comment = fun_outer(comment)
comment()

如果外部函数的参数是函数类型,并且在内部函数调用,那么这个闭包就是装饰器。 
2. 语法糖
def fun_outer(func):
def fun_inner():
func()
print('这是我添加的额外功能')
return fun_inner
@fun_outer
def comment():
print('这是我的已有函数!')
comment()
'''
注意:
1. 语法糖和函数中间不可以添加任何代码,并且后面必须跟被装饰函数
2. 语法糖放在那个函数前面,那么它修饰的就是那个函数
'''
可以打上几个断点 观察详细运行结果: 
3. 装饰器装饰和调用哪个先进行?
def fun_outer(func):
print('1')
def fun_inner():
print('2')
func()
print('3')
print('4')
return fun_inner
@fun_outer
def comment():
print('这是我的已有函数!')
'''
注意:
装饰器不是在调用时开始装饰的,而是运行到13行的时候就开始进行装饰了。
'''

4. 练习:从1打印到10000执行的时间
import time
def fun_outer(func):
def fun_inner():
begin = time.time()
func()
end = time.time()
res = end - begin
print('函数执行所耗时:', res)
return fun_inner
@fun_outer
def work():
for i in range(10000):
print(i)
work()

5. 装饰器的应用
1. 装饰带有参数的函数
def fun_outer(func):
def fun_inner(a, b):
print('正在计算 {} + {}'.format(a, b))
func(a, b)
print('计算完毕!')
return fun_inner
@fun_outer
def add(a, b):
c = a + b
print('{} + {} = {}'.format(a, b, c))
add(1, 2)

2. 装饰带有参数和返回值的函数
def fun_outer(func):
def fun_inner(a, b):
print('正在计算 {} + {}'.format(a, b))
res = func(a, b)
return res
return fun_inner
@fun_outer
def add(a, b):
return a + b
sum_a_b = add(1, 2)
print(sum_a_b)
 注意: 如果没有返回值,默认为None 
3. 装饰带有不定长参数和返回值的函数
def fun_outer(func):
def fun_inner(*args, **kwargs):
print('正在执行加法运算:')
num = func(*args, **kwargs)
return num
return fun_inner
@fun_outer
def add_num(*args, **kwargs):
result = 0
for i in args:
result += i
for value in kwargs.values():
result += value
return result
re = add_num(1, 2, a=10, b=20)
print(re)

4. 带参数的装饰器
def def_outer(a=0):
def fun_outer(func):
def fun_inner():
print('参数:', a)
func()
return fun_inner
return fun_outer
@def_outer(6)
def comment():
print("hello world")
comment()

|