详解Python中的装饰器(Decorator)-详解Python中的@符号

其他关于Python的总结文章请访问:https://blog.csdn.net/qq_38962621/category_10299380.html

详解Python中的装饰器(Decorator)-详解Python中的@符号

本质上,装饰器(decorator)就是一个能够返回函数的高阶函数,比如说我们有很多个函数A、B、C、D等等,我们希望有一个功能是在执行一个函数之前打印这个函数的名字,当然我们可以给每个函数的第一句手动加上打印名字的代码,或者我们在每次调用前都使用 print(function.__name__) 来打印它的名字,但是这显然是很麻烦的,装饰器提供了一种不需要更改原函数,但是可以动态地为函数增加功能的方式。原理很简单,我们可以创建一个返回函数的函数,在外层的函数中增加一个打印调用函数名称的代码,然后返回内部的函数。

简单的不带参数的装饰器

比如一个简单的函数:

def funcA():
    print("hello world")

然后定义一个高阶函数:

def log(function):
    def wrapper(*args,**kwargs):
        print("Call {}".format(function.__name__))
        return function(*args,**kwargs)
    return wrapper

这样我们调用 log(funcA) 即达到我们的需求:

Call funcA
hello world

而装饰器提供了一个更简单的方式:使用@符号来完成:将 @decoratorName 放在希望使用装饰器来调用的函数前即可(使用装饰器的函数需要定义在装饰器的定义之后,即需要先定义 log 函数再定义带有 @log 装饰器的 funcA 函数:

@log
def funcA():
    print("hello world")

这样再调用 funcA 就是调用使用了装饰器的 funcA,即现在 funcA = log(funcA)

带有参数的装饰器

现在考虑如果装饰器本身希望传入参数,那就需要一个返回decorator的高阶函数:

def log(text):
    def decorator(function):
        def wrapper(*args,**kwargs):
            print("Call {} with {}".format(function.__name__,text))
            return function(*args,**kwargs)
        return wrapper
    return decorator

@log('some text')
def funcA():
    print("hello world")

funcA()

这样得到的结果就是:

Call funcA with some text
hello world

此时调用funcA实际上等价于调用了 log("some text")(funcA)

解决函数名字的错位问题

此时我们可以看到,funcA不再是原来的funcA,而实际是在log函数中返回的那个 wrapper 函数,所以如果我们检测此时的 funcA.__name__ 会发现并不是 'funcA' 而是 'wrapper',这其实是不好的,可以使用包 functools 中的使 functools.wraps 装饰器来解决,所以一个完整装饰器应该这样定义:

import functools

def log(function):
    @functools.wraps(function)
    def wrapper(*args,**kwargs):
        print("Call {}".format(function.__name__))
        return function(*args,**kwargs)
    return wrapper

以及:

import functools

def log(text):
    def decorator(function):
        @functools.wraps(function)
        def wrapper(*args,**kwargs):
            print("Call {} with {}".format(function.__name__,text))
            return function(*args,**kwargs)
        return wrapper
    return decorator
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值