装饰的执行顺序
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()
输出:"<b><i>hello world</i></b>"
装饰的执行顺序
我大致了解关于装饰,以及它如何在大多数例子是一个工作。
在这个例子中,有2个。从输出看来,@make_italic
似乎首先执行,然后@make_bold
。
这是否意味着对于装饰函数,它将首先运行函数,然后移动到其他装饰器的顶部?像@make_italic
先是@make_bold
,而不是相反。
那么这意味着它与大多数编程语言中的自顶向下方法的规范不同?只是为了装饰者的这种情况?或者我错了?
装饰者包装他们装饰的功能。所以make_bold
修饰了装饰者make_italic
的结果,其中装饰了hello
功能。
@decorator
语法实际上只是语法糖;以下内容:
@decorator
def decorated_function():
# ...
如确实执行:
def decorated_function():
# ...
decorated_function = decorator(decorated_function)
替换原始decorated_function
对象与任何decorator()
返回。
堆叠装饰器重复该过程向外。
所以你的样品:
@make_bold
@make_italic
def hello():
return "hello world"
可扩展到:
def hello():
return "hello world"
hello = make_bold(make_italic(hello))
当你调用hello()
现在,您呼叫的make_bold()
返回的对象,真的。 make_bold()
返回lambda
,它调用函数make_bold
包装,这是返回值make_italic()
,这也是一个lambda,它调用原始hello()
。展开所有这些调用你:
hello() = lambda : "<b>" + fn() + "</b>" # where fn() ->
lambda : "<i>" + fn() + "</i>" # where fn() ->
return "hello world"
所以输出变成:
"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"
我的理解开始。但是这是否意味着在这种情况下有2个包装器时,IDE会自动检测并包装第一个包装器的结果?因为我认为'@make_bold #make_bold = make_bold(hello)' '@make_italiC#make_italic = make_italic(hello)'?我不确定是否基于此,它会包装第一个结果。或者对于这两个包装器的情况,IDE将使用'make_bold(make_italic(hello))'来代替我分享的内容。 – Newbie 2014-12-07 11:38:03
@Newbie:你的IDE在这里什么也不做;它是* Python *的包装。我在最后一个示例中展示了make_bold()包装'make_italic()'的输出,该输出用于包装'hello',所以相当于'make_bold(make_italic(hello))'。 – 2014-12-07 11:40:41
您能否提供此代码的版本而不使用lambda?我曾尝试.format但不起作用。为什么在这个例子中使用lambda?我试图理解lambda以及它在这个例子中是如何工作的,但仍然有问题。我得到的lambda就像一行函数,与def函数的规范相比,它可以很容易地传递? – Newbie 2014-12-07 12:20:38
是的,它从下往上传递结果到下一个 – 2014-12-07 11:28:37