为了更好的理解Decorators(装饰器),首先要理解什么是function(函数/方法)? 函数就是 一段代码块, 它基于给定的传入参数,返回有意义的值,或者执行特定的操作。
比如:
def test_add(a, b):
return a + b
在Python中, 函数也是一种对象,所以本身也可以作为函数的传入参数来使用,这就为装饰器的产生提供了必要的条件, Decorators(装饰器)是Python中相对高级的功能,简单来说, 就是让被装饰的函数在没有显式代码修改的情况下,就能够具备特定的功能,而这个特定的功能就是我们在装饰器中预先定义好的。
假定我们现在要实现一个装饰器,这个装饰器的功能就是打印函数的返回值,那我们应该怎么来做呢?
- 首先,定义一个装饰器:
def print_result(func):
def wapper(a, b):
name = func.__name__
result = func(a, b)
print "{} return: {}".format(name, result)
return result
return wapper
- 然后给函数添加装饰器。如何添加呢? 很简单就在函数的上方添加“@decorator_name”, 而本例的详细代码如下:
from test_deco import print_result
@print_result
def test_add(a, b):
return a + b
- 最后调用已经添加了装饰器的函数
test_add(3, 4)
输出:
test_add return: 7
通过给函数添加装饰器,在不修改函数代码的情况下,实现了函数功能的扩展。此外,该装饰器并非只适用于本例中的方法,它应该适用于所有传入参数是两个,并且有返回值的函数。当然,通过一定的修改,可以让该装饰器,适用于所有方法,而不局限于传入参数的个数。
为了让我们的装饰器适用于可以装饰所有的函数,那么我们需要解决两个问题:
(1), 装饰器必须可以适配任意数量的传入参数, 代码修改如下:
def print_result(func):
def wapper(*args, **kwargs):
name = func.__name__
result = func(*args, **kwargs)
print "{} return: {}".format(name, result)
return result
return wapper
(2), 装饰器必须可以适配没有返回值的函数, 代码修改如下:
def print_result(func):
def wapper(*args, **kwargs):
name = func.__name__
result = func(*args, **kwargs)
result = "No return" if result is None else result
print "{} return: {}".format(name, result)
return result
return wapper
经过这样的修改后,装饰器"print_result"具备了装饰所有方法的能力。我们来看一看测试代码结果吧:
from test_deco import print_result
@print_result
def test_add(a, b):
return a + b
@print_result
def test_sum(a, b, c):
return a + b + c
@print_result
def test_none():
pass
test_add(3, 4)
test_sum(3, 4, 5)
test_none()
输出:
test_add return: 7 test_sum return: 12 test_none return: No return
综上所示,当我们需要对所有的函数或者一批函数进行功能扩展的时候,我们就可以考虑使用装饰器,它不但可以实现对现有的函数进行特定的功能扩展,也可以根据需要给将来要开发的新函数提供功能扩展。并且,这样的扩展是如此简单和方便, 也如此优雅和灵活。
知识点:
1. 位置参数
def func(a, b), a和b都是位置参数,其实也就是我们口中的普通传入参数
为什么叫作位置参数呢,因为调用函数时会根据函数定义的参数位置来传递参数
2. 可变数量的位置参数
def func(*args), args表示任意数量的传入参数列表,也就是说,传入的参数数量可以是0个,1个或者多个。
通过*进行解构(Unpacking)
3. 参数的默认值
def func(words="Hello"):
print words
我们给传入参数words设定了默认值"Hello", 所以在调用的时候如果不传入参数words,那么函数就会把words的值设定为默认值"Hello"
4. 关键字参数
def func(name="Jim", age=100):
info = {"name": "Jim:, "age": 100}
return info
(name="Jim", age=100)就是函数func的关键字参数。 此外关键字参数之间不要求先后顺序
细心的同学不难看出,如果我们不看函数体,其实无法区分究竟是参数的默认值,还是关键字参数。但看一看函数体就一目了然了。当然,他们之间的不同在调用的时候也有体现。
5. 可变长度的关键字参数
def func(**kwargs):
return kwargs
kwargs表示传入参数字典,也就是说kwargs的keys()的长度是任意的,并且keys()和values()的值也是任意的。
通过**进行解构(Unpacking)