New*_*bie 72 python decorator python-decorators
def make_bold(fn):
return lambda : "<b>" + fn() + "</b>"
def make_italic(fn):
return lambda : "<i>" + fn() + "</i>"
@make_bold
@make_italic
def hello():
return "hello world"
helloHTML = hello()
Run Code Online (Sandbox Code Playgroud)
输出: "<b><i>hello world</i></b>"
我大致了解装饰器以及它在大多数示例中如何与其中一个一起工作.
在这个例子中,有2个.从输出,它似乎@make_italic首先执行,然后@make_bold.
这是否意味着对于装饰函数,它将首先运行函数然后移动到其他装饰器的顶部?就像@make_italic第一个@make_bold,而不是相反.
那么这意味着它与大多数编程中的自上而下方法的规范不同?只为这个装饰器的情况?还是我错了?
Mar*_*ers 97
装饰者包装他们正在装饰的功能.所以make_bold装饰了make_italic装饰器的结果,它装饰了这个hello功能.
该@decorator语法真的只是语法糖; 下列:
@decorator
def decorated_function():
# ...
Run Code Online (Sandbox Code Playgroud)
真的被执行为:
def decorated_function():
# ...
decorated_function = decorator(decorated_function)
Run Code Online (Sandbox Code Playgroud)
用返回的内容替换原始decorated_function对象decorator().
堆叠装饰器重复向外处理.
所以你的样本:
@make_bold
@make_italic
def hello():
return "hello world"
Run Code Online (Sandbox Code Playgroud)
可以扩展到:
def hello():
return "hello world"
hello = make_bold(make_italic(hello))
Run Code Online (Sandbox Code Playgroud)
当你hello()现在打电话的时候,你正在调用返回的对象make_bold().make_bold()返回一个lambda调用函数make_boldwrapped,它是返回值make_italic(),也是一个调用原始函数的lambda hello().扩展所有这些来电:
hello() = lambda : "<b>" + fn() + "</b>" # where fn() ->
lambda : "<i>" + fn() + "</i>" # where fn() ->
return "hello world"
Run Code Online (Sandbox Code Playgroud)
所以输出变成:
"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"
Run Code Online (Sandbox Code Playgroud)
rka*_*ach 25
我认为这个问题的答案似乎很简单,但事实并非如此。当我们谈论装饰器的执行顺序时,我认为我们必须记住装饰器本身在执行过程中的不同时刻进行评估:当Python解释器评估装饰方法定义本身时以及调用/执行装饰方法时。正如我在实验中看到的,这两个阶段的装饰器顺序是不同的。
此外,请记住,在装饰函数时,我们可以让代码在被装饰的方法之前执行,并在之后运行。这使得嵌套装饰器时事情变得更加复杂。
所以,简而言之:
考虑以下代码示例:
print("========== Definition ==========")
def decorator(extra):
print(" in decorator factory for %s " % extra)
extra = " %s" % extra
def inner(func):
print(" defining decorator %s " % extra)
def wrapper(*args, **kwargs):
print("before %s -- %s" % (func.__name__, extra))
func(*args, **kwargs)
print("after %s -- %s" % (func.__name__, extra))
return wrapper
return inner
@decorator('first')
@decorator('middle')
@decorator('last')
def hello():
print(' Hello ')
print("\n========== Execution ==========")
hello()
Run Code Online (Sandbox Code Playgroud)
该代码的输出如下:
========== Definition ==========
in decorator factory for first
in decorator factory for middle
in decorator factory for last
defining decorator last
defining decorator middle
defining decorator first
========== Execution ==========
before wrapper -- first
before wrapper -- middle
before hello -- last
Hello
after hello -- last
after wrapper -- middle
after wrapper -- first
Run Code Online (Sandbox Code Playgroud)
正如我们在此输出中看到的,顺序是不同的(如前面所解释的)。在定义期间,装饰器从下到上评估,而在执行期间(通常是最重要的部分),它们从上到下评估。
回到问题中提出的示例,以下是示例代码(不使用 lambda):
print("========== Definition ==========")
def make_bold(fn):
print("make_bold decorator")
def wrapper():
print("bold")
return "<b>" + fn() + "</b>"
return wrapper
def make_italic(fn):
print("make_italic decorator")
def wrapper():
print("italic")
return "<i>" + fn() + "</i>"
return wrapper
@make_bold
@make_italic
def hello():
return "hello world"
print("\n========== Execution ==========")
print(hello())
Run Code Online (Sandbox Code Playgroud)
本例中的输出:
========== Definition ==========
make_italic decorator
make_bold decorator
========== Execution ==========
bold
italic
<b><i>hello world</i></b>
Run Code Online (Sandbox Code Playgroud)
新的执行顺序是从上到下。我们可以将相同的方法应用于原始代码(稍微修改一下以打印我们在哪里):
print("========== Definition ==========")
def make_bold(fn):
print("make_bold")
return lambda: print("exec_bold") or "<b>" + fn() + "</b>"
def make_italic(fn):
print("make_italic")
return lambda: print("exec_italic") or "<i>" + fn() + "</i>"
@make_bold
@make_italic
def hello():
return "hello world"
print("\n========== Execution ==========")
print(hello())
Run Code Online (Sandbox Code Playgroud)
输出是:
========== Definition ==========
make_italic
make_bold
========== Execution ==========
exec_bold
exec_italic
<b><i>hello world</i></b>
Run Code Online (Sandbox Code Playgroud)
我希望这能让您对 Python 中的装饰器顺序及其处理方式有所了解。
| 归档时间: |
|
| 查看次数: |
23982 次 |
| 最近记录: |