装饰器-阿里云开发者社区

开发者社区> 云计算> 正文

装饰器

简介: python

As we know,装饰器的作用是在不改变原函数逻辑和调用方式的情况下为函数附加新的功能。

def hello():
    print('hello world!')
    return 1

一个非常简单的函数,现在在输出hello world!之前输出星号,在输出hello world!之后输出等号,装饰器如下

def deco():
    def inner(func):
        print('*'*12)
        func()
        print('='*12)
    return inner

原函数使用装饰器

@deco
def hello():
    print('hello world!')
    return 1

调用函数即可看到如下输出
image.png
使用@符号相当于执行了以下两步

hello = deco(hello)
hello()

函数也是一个对象,可以当作参数传递给其它函数,第一步把hello当作参数传递给deco函数,deco返回inner函数,然后在把inner函数赋值给hello,这样的话再次调用hello的时候其实执行的是inner的逻辑,由于把原hello函数当作参数传递给了inner,所以在inner内调用原函数即可。
但是,这样的装饰器是有问题的

原函数返回值

原函数是有返回值的,但是经过装饰器调用之后把inner赋值给了原函数,然而inner无返回值,这就尴尬了,所以要让inner返回原函数的返回值

def deco(func):
    def inner():
        print('*' * 12)
        ret = func()  # 接收原函数返回值
        print('=' * 12)
        return ret
    return inner

返回值问题解决了,但是,函数名却变了

函数名问题

没使用装饰器的时候

print(hello.__name__)  # 输出hello

使用装饰器后

@deco
def hello():
    pass
print(hello.__name__)  # 输出inner

函数名变了,好像也不太对~
解决这个问题,使用内置模块functools改造装饰器

def deco(func):
    @functools.wraps(func)
    def inner():
        ret = func()
        return ret
    return inner

这样的装饰器只能用于没有参数的函数,对于有参数的函数怎么搞?

函数参数

def deco(func):
    @functools.wraps(func)
    def inner(*args, **kwargs):
        ret = func(*args, **kwargs)
        return ret
    return inner

因为给函数使用装饰器后,原函数其实就变成了装饰器的内部函数,那么原函数的参数就是传递给装饰器的内部函数,装饰器的内部函数就要能够接收参数

给装饰器指定参数

def deco_params(*arg, **kw):
    def deco(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
            ret = func(*args, **kwargs)
            return ret
        return inner
    return deco

使用装饰器

@deco_params(1, 2)
def hello(a, b):
    pass

调用过程

deco = deco_params(1, 2)
hello = deco(hello)
hello(3, 4)

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
云计算
使用钉钉扫一扫加入圈子
+ 订阅

时时分享云计算技术内容,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。

其他文章