什么是装饰器?
简单点解释:装饰器就是一个可调用对象,其参数是被其装饰的可调用对象
是不是感觉有点绕?稍微具体一点解释:
因为函数在 Python 中是一等公民,所以一个函数可以接收另一个函数作为参数并返回一个新的函数,这样的一个函数就被称之为装饰器(这里先不讨论装饰类的情况)。
举个栗子:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# 定义一个装饰器
def add_prefix(func):
def inner_func(args):
return '/home/xieyanke/' + args
return inner_func
@add_prefix
def test(path):
return path
if __name__ == '__main__':
print(test('factory')) # 输出结果为:/home/xieyanke/factory
装饰器何时执行?
装饰器在 Python 模块导入时便执行了,所以装饰器在所有被装饰函数之前执行,也优先于被导入模块内所有可执行对象执行。
示例:my_decorator.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
def dec(func):
print('my_decorator running...')
return func
示例:main.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from my_decorator import dec
@dec
def main1():
print('func: main1 running')
def main2():
print('func: main2 running')
if __name__ == '__main__':
main2()
main1()
# 执行结果:
# my_decorator running...
# func: main2 running
# func: main1 running
多个装饰器的执行顺序是什么?
假如一个函数被多个装饰器装饰,那么这些装饰器的执行顺序为自底向上执行
示例:main.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
def dec1(func):
print("dec1 running...")
return func
def dec2(func):
print("dec2 running...")
return func
@dec1
@dec2
def main():
print('func: main running')
if __name__ == '__main__':
main()
## 执行结果:
# dec2 running...
# dec1 running...
# func: main running
# 从结果可以看出多个装饰器的执行顺序为自底向上执行
装饰器如何接收参数?
如果我们使用一些其他框架例如:Flask ,经常发现框架中的装饰器是可以接收参数的。我们如何自定义一个可以接收普通参数的装饰器呢?
答案是:还真不能定义一个可以接收普通参数的装饰器。那么别人的框架是怎么实现的呢?其实这里面涉及到了闭包与自由变量的语法糖(关于闭包与自由变量后期会单独写一篇详细介绍,这里先带过了),那么要实现一个看着像可以接收普通参数的装饰器,需要先定义一个函数接收普通参数,然后返回这个函数内部实现的装饰器,这样就实现了一个看似可以接收普通参数的装饰器。
示例:main.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
def dec1(arg):
def dec(func):
print("dec1 receive args: " + arg)
return func
return dec
@dec1('arg_demo')
def main1():
print('func: main1 running')
if __name__ == '__main__':
main1()
最后说一说为什么要使用装饰器?
- 想用装饰器的内容替换被装饰函数的内容
- 想用装饰器的内容改进被装饰函数的内容
- 想把被装饰函数注册到某处
- 想在被装饰函数的执行前后做一些操作
- 交流可以加 QQ 群:397234385
- 或者 QQ 扫码入群:
网友评论