1 装饰器的引入
在日常需求开发中,假使我们需要对已经开发上线的程序添加某些功能,但是又不能对程序中函数的源代码进行修改,该如何处理呢?此时,就需要使用到Python中的装饰器(Decorator)。
2 Python闭包
2.1 函数也是一个对象
在讲闭包之前,首先明确一点:在Python中,一切皆对象。因此,Python中函数也是一个对象:
def add(a, b):
return a + b
print(type(add)) # <class 'function'>
此时,我们可以给add
这个函数对象起个别名为my_add
,但是其仅仅是一个函数对象,如果要进行函数调用,需要写成my_add(*args, **kwargs)
:
my_add = add
print(my_add) # <function add at 0x7fca90ac1d30>
print(my_add(2, 3)) # 5
2.2 高阶函数
在Python中,满足下列条件之一的函数,我们称之为高阶函数:
- 接收函数作为参数
- 返回值是一个函数对象
例如:
def add(a, b):
return a + b
def my_func(func):
return func
my_add = my_func(add)
print(my_add(2, 3)) # 5
2.3 闭包
如果一个函数定义在另一个函数的作用域内,并且引用了外层函数的变量,则该函数称为闭包(Closure):
def outer():
a = 2
b = 3
def inner():
sum_ = a + b
return sum_
return inner
my_func = outer()
print(my_func()) # 5
3 装饰器
3.1 一个简单的装饰器
import time
def timer(func):
def inner():
start = time.time()
func()
end = time.time()
print("{} 函数运行用时{:.2f}秒".format(func.__name__, (end - start)))
return inner
def my_print():
print("Hello Python!")
time.sleep(1)
my_print = timer(my_print)
my_print()
输出结果:
Hello Python!
my_print 函数运行用时1.00秒
3.2 语法糖的实现
在上述代码中,稍作修改,使用@timer
即可对my_print()
函数进行装饰:
import time
def timer(func):
def inner():
start = time.time()
func()
end = time.time()
print("{} 函数运行用时{:.2f}秒".format(func.__name__, (end - start)))
return inner
@timer
def my_print():
print("Hello Python!")
time.sleep(1)
my_print()
3.3 装饰器的一般写法
对于函数需要进行传参的一般情况下,我们使用*args, **kwargs
进行参数解包操作:
import time
def timer(func):
def inner(*args, **kwargs):
start = time.time()
sum_ = func(*args, **kwargs)
end = time.time()
print("{} 函数运行用时{:.2f}秒".format(func.__name__, (end - start)))
return sum_
return inner
@timer
def add(a, b):
time.sleep(1)
return a + b
print(add(2, 3))
输出结果:
add 函数运行用时1.00秒
5