聊聊Python的装饰器(Decorators)

为了更好的理解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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lemon2050

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值