python装饰器

Python装饰器是Python的一个重要部分,作用是修改其他函数,并且不会影响调用方式,根据我个人的理解,梳理一下思路,帮助理解装饰器。

首先,Python中万物皆对象,对于函数,可以直接赋值:

def hi():
    return 'hi'
print(hi())
#output: ‘hi’
#可以直接把函数赋值给变量 hello = hi print(hello()) #output: 'hi'
#并且删除原函数后,依然可以调用hello del hi print(hello()) #output: 'hi'

函数内部也可以定义函数:

def hi():
    def hello():
        return 'hello'
    return hello()

print(hi())
#output: 'hello'

函数还可以作为参数或者返回值:

def hi():
    def hello():
        return 'hello'
    return hello

#将hello赋值给Greetings 
Greetings = hi()
print(Greetings())
#或者
print(hi()())
#output: 'hello'
def hi():
    return 'hi'

def hello(func_name):
    return func_name()

#将hi作为hello的参数
print(hello(hi))
#output: 'hi'

有了上面的理解,可以作出下面的写法:

def hi():
    print('hi')

def decorator(func_name):
    def wrapTheFunction():
        print('before hi')
        func_name()
        print('after hi')
    return wrapTheFunction

hi = decorator(hi)
hi()
#outputs:
before hi #     hi #     after hi

所以,这样其实就得到了一个装饰器,装饰器做的事情就是封装一个函数,添加一些动作然后再返回来。

然后‘@’符号,其实就是一种方便的用法,方便的生成一个被装饰的函数,有了@,就不用自己去hi = decorator(hi)这样赋值了

上面的写法虽然表面上看已经实现了我们改变hi这个函数的功能的需要,但是由于hi = decorator(hi)这个赋值,其实hi指向的是wrapTheFunction函数,通过打印hi.__name__就可以发现,

出来的结果是#wrapTheFunction,专业的说法是它重写了我们函数的名字和注释文档(docstring)。所以要实现最终的目的,还需要一个系统提供的函数functools.wraps。

@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

更改后的写法如下:

 

from functools import wraps

def decorator(func_name):
    @wraps(func_name)
    def wrapTheFunction():
        print('before hi')
        func_name()
        print('after hi')
    return wrapTheFunction

@decorator
def hi():
    print('hi')
print(hi.__name__)
#output:hi

 

至此,就是完全体的装饰器了。终于明白了。

 

装饰器最大的作用,就是在不影响原函数的调用方式上,不需要修改原函数的代码,而对原函数的功能进行扩充,当然,装饰器本质上还是函数,所以它同时有函数的优点,即可复用性,

所以写出一个装饰器,不仅仅可以增加一个函数的功能,以后其他函数也有类型需求的时候直接拿过来就就行了,这就是相比直接修改原函数的优势。

你可能感兴趣的:(python装饰器)