Source:
Primer on Python Decorators – Real Python
<aside> <img src="/icons/forward_gray.svg" alt="/icons/forward_gray.svg" width="40px" /> Get Your Code: Click here to download the free sample code that shows you how to create and use Python decorators.
</aside>
<aside> <img src="/icons/forward_gray.svg" alt="/icons/forward_gray.svg" width="40px" /> Free Bonus: Click here to get access to a free "The Power of Python Decorators" guide that shows you three advanced decorator patterns and techniques you can use to write cleaner and more Pythonic programs.
</aside>
<aside> <img src="/icons/forward_gray.svg" alt="/icons/forward_gray.svg" width="40px" /> Decorators Cheat Sheet: Click here to get access to a free three-page Python decorators cheat sheet that summarizes the techniques explained in this tutorial.
</aside>
<aside> <img src="/icons/forward_gray.svg" alt="/icons/forward_gray.svg" width="40px" /> Decorators Q&A Transcript: Click here to get access to a 25-page chat log from our Python decorators Q&A session in the Real Python Community Slack where we discussed common decorator questions.
</aside>
为了了解装饰器(Decorators),必须先了解函数工作原理的一些细节。函数有很多方面,但是在装饰器种,一个函数根据给定的参数值返回一个值,以下是一个基本的例子:
>>> def add_one(number):
... return number + 1
...
>>> add_one(2)
3
总体来说,Python中的函数除了将输入转为输出外还有其他的作用(side effect)。print()
函数就是一个例子:它返回None
,同时会向console输出一些信息。但是,将函数想成一个转换参数到输出值的工具已足以了解装饰器(Decorators)
在函数式编程 functional programming中,几乎完全使用没有其他作用(side effect)的纯函数。Python 虽然不是纯函数式语言,但它支持许多函数式编程概念,包括将函数视为一级对象 first-class objects。
这意味着**函数(**function)可以作为参数传递和使用,就像任何其他的对象(object)一样,如str,int,float,list等等。
def say_hello(name):
return f"Hello {name}"
def be_awesome(name):
return f"Yo {name}, together we're the awesomest!"
def greet_bob(greeter_func):
return greeter_func("Bob")
以上例子中,say_hello()
和 be_awesome()
是常规函数, 需要获取一个string类型的name。而 greet_bob()
函数需要获取一个函数作为参数,例如你可以将say_hello()
或 be_awesome()
函数作为输入。
为了测试你的函数,你可以在交互模式(interactive mode)中运行你的代码。这需要使用 -i
。例如,如果你的代码在一个名为greeters.py
的文件里,那么你应该运行 python -i greeters.py
:
>>> greet_bob(say_hello)
'Hello Bob'
>>> greet_bob(be_awesome)
'Yo Bob, together we're the awesomest!'
注意 greet_bob(say_hello)
指向两个函数,greet_bob()
和 say_hello()
,但是是以不同的方式。say_hello
函数的命名没有括号,这表示只传递对函数的引用,未执行该函数。greet_bob()
函数写了括号,所以它会被正常调用。