我决定分为三个方面来认识和学习装饰器:
1.什么是装饰器?
2.装饰器的工作过程及如何使用装饰器?
3.装饰器有什么用?我可以用装饰器做什么?
首先,我们要从函数开始说起。
函数是对象,因此,具有功能:
1.可以分配给变量
2.可以在另一个函数中定义
这意味着一个函数可以是return另一个函数。
举个栗子:
def getTalk(kind="shout"):
def shout(word="yes"):
return word.capitalize()+"!"
def whisper(word="yes") :
return word.lower()+"...";
# Then we return one of them
if kind == "shout":
# We don't use "()", we are not calling the function,
# we are returning the function object
return shout
else:
return whisper
talk = getTalk()
print(talk)
outputs:
<function getTalk.<locals>.shout at 0x7f916c065268>
print(talk())
outputs:
Yes!
print(getTalk("whisper")())
outputs:
yes...
def doSomethingBefore(func):
print("I do something before then I call the function you gave me")
print(func())
doSomethingBefore(talk)
outputs:
I do something before then I call the function you gave me
Yes!
装饰器是“包装器(wrapper)”,这意味着它们允许你在它们装饰的函数之前和之后执行代码而不修改函数本身。
def my_shiny_new_decorator(a_function_to_decorate):
def the_wrapper_around_the_original_function():
print("Before the function runs")
a_function_to_decorate()
print("After the function runs")
# At this point, "a_function_to_decorate" HAS NEVER BEEN EXECUTED.
# We return the wrapper function we have just created.
# The wrapper contains the function and the code to execute before and after. It’s ready to use!
return the_wrapper_around_the_original_function
# Now imagine you create a function you don't want to ever touch again.
def a_stand_alone_function():
print("I am a stand alone function, don't you dare modify me")
a_stand_alone_function()
outputs:
I am a stand alone function, don't you dare modify me
a_stand_alone_function_decorated = my_shiny_new_decorator(a_stand_alone_function)
a_stand_alone_function_decorated()
outputs:
Before the function runs
I am a stand alone function, don't you dare modify me
After the function runs
#使用装饰器语法,@decorator只是一个快捷方式:another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)
#装饰器只是装饰器设计模式的pythonic变体。Python中嵌入了几种经典设计模式以简化开发(如迭代器)。
@my_shiny_new_decorator
def another_stand_alone_function():
print("Leave me alone")
another_stand_alone_function()
outputs:
Before the function runs
Leave me alone
After the function runs
积累装饰器和使用装饰器语法:
#积累装饰器
def bread(func):
def wrapper():
print("</''''''\>")
func()
print("<\______/>")
return wrapper
def ingredients(func):
def wrapper():
print("#tomatoes#")
func()
print("~salad~")
return wrapper
def sandwich(food="--ham--"):
print(food)
sandwich()
outputs:
--ham--
sandwich = bread(ingredients(sandwich))
sandwich()
outputs:
</''''''\>
#tomatoes#
--ham--
~salad~
<\______/>
#使用python装饰器语法
@bread
@ingredients
#@bread和@ingredients相当于sandwich = bread(ingredients(sandwich))的缩写(快捷方式)
def sandwich(food = '--ham--'):
print(food)
sandwich()
outputs:
</''''''\>
#tomatoes#
--ham--
~salad~
<\______/>
#积累装饰器也可以随意顺序,输出将随之改变
@ingredients
@bread
def sandwich(food = '--ham--'):
print(food)
sandwich()
outputs:
#tomatoes#
</''''''\>
--ham--
<\______/>
~salad~
将参数传递给修饰函数以及将参数传递给装饰器:
#将参数传递给修饰函数
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print("I got args! Look: {0}, {1}".format(arg1, arg2))
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print("My name is {0} {1}".format(first_name, last_name))
print_full_name("Peter", "Venkman")
outputs:
I got args! Look: Peter, Venkman
My name is Peter Venkman
#将参数传递给装饰器
def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
print("I make decorators! And I accept arguments: {0}, {1}".format(decorator_arg1, decorator_arg2))
def my_decorator(func):
print("I am the decorator. Somehow you passed me arguments: {0}, {1}".format(decorator_arg1, decorator_arg2))
def wrapped(function_arg1, function_arg2) :
print("I am the wrapper around the decorated function.\n"
"I can access all the variables\n"
"\t- from the decorator: {0} {1}\n"
"\t- from the function call: {2} {3}\n"
"Then I can pass them to the decorated function"
.format(decorator_arg1, decorator_arg2,
function_arg1, function_arg2))
return func(function_arg1, function_arg2)
return wrapped
return my_decorator
@decorator_maker_with_arguments("Leonard", "Sheldon")
def decorated_function_with_arguments(function_arg1, function_arg2):
print("I am the decorated function and only knows about my arguments: {0}"
" {1}".format(function_arg1, function_arg2))
decorated_function_with_arguments("Rajesh", "Howard")
outputs:
I make decorators! And I accept arguments: Leonard, Sheldon
I am the decorator. Somehow you passed me arguments: Leonard, Sheldon
I am the wrapper around the decorated function.
I can access all the variables
- from the decorator: Leonard Sheldon
- from the function call: Rajesh Howard
Then I can pass them to the decorated function
I am the decorated function and only knows about my arguments: Rajesh Howard
python装饰器堪称神器之一,还有其他的应用场景,笔者暂时还未真正接触和感受到,所以等以后用到再行补充,但此刻已对python装饰器了解了有三分,对此功能十分敬佩,希望后续能多多用到。下面来说说最后一点,就是python装饰器有什么用?以及用python装饰器可应用于什么场景?(目前作为一个大三学生,能接触的应用场景有限)
stackoverflow上有一句对装饰器好处的总结挺到位:
装饰器的好处在于你几乎可以在没有重写的情况下立即使用它们。所以,简单来说,python装饰器是语法糖,可以缩小代码规模,这应该显而易见。当然,还有增加代码复用。应用场景的话,由简到繁的看以上例子,耐心读完都能理解,也能感受到这个语法糖的“甜”吧。
本篇是笔者看了两天关于装饰器的相关内容做的笔记,一定有所不足,更多的内容可以参考以下链接。有大神有更多指点和其他分享的都可私信,必当虚心学习!
附上参考链接:
https://stackoverflow.com/questions/739654/how-to-make-a-chain-of-function-decorators