在 Python 中格式化装饰器
Format a decorator in Python
咆哮 - 为什么人们说 'a decorator is a function that returns another function'?这个定义没有意义,因为如果装饰器就是这样,为什么不只使用第二个函数而不用第一个呢? - 结束咆哮
幸运的是,我在这里找到了一个更合理的定义:
http://thecodeship.com/patterns/guide-to-python-function-decorators/
不幸的是,我还是不明白这些例子,比如这个:
def get_text(name):
return "lorem ipsum, {0} dolor sit amet".format(name)
def p_decorate(func):
def func_wrapper(name):
return "<p>{0}</p>".format(func(name))
return func_wrapper
my_get_text = p_decorate(get_text)
print my_get_text("John")
#Outputs "<p>lorem ipsum, John dolor sit amet</p>"
请注意,post 已有两年多了,作者尚未对任何评论做出回应。
这是我的问题:为什么不输出
"<p>John</p>"
还是错误?整个字符串如何进入 p 标签而不只是名称?
编辑:我刚刚发现您链接了一篇文章,从字面上逐步解释了装饰器是什么...但是已经输入了,所以...
Python 中有一个称为闭包/函数闭包的特性。
自从我试图解释/理解闭包/装饰器在较低级别发生的事情以来已经有一段时间了,所以这实际上可能是错误的。
函数func_wrapper每次调用p_decorate
时都会被重新定义,func_wrapper会记住包含的内容 命名空间在定义时的样子。
什么意思:
例如,假设您有一些嵌套在 p_decorate
中的外部变量,您会期望这会引发错误,因为当 func_wrapper
被调用并尝试使用这个变量,但它不会,因为封闭的命名空间是 "remembered"
在 python 3 中是 __closure__
,在 python 2 中是 func_closure
以下。
def get_text(name):
return "lorem ipsum, {0} dolor sit amet".format(name)
def p_decorate(func):
def func_wrapper(name):
return "<p>{0}</p>".format(func(name)) #Cached result
print(func_wrapper.func_closure)
return func_wrapper
my_get_text1 = p_decorate(get_text)
my_get_text2 = p_decorate(get_text2)
func_closure 东西:
my_get_text1 >>> (<cell at 0x*: function object at 0x*>,)
my_get_text2 >>> (<cell at 0x(different address): function object at (diff address)>,)
我们没有将不同的函数传递给 func_wrapper
函数,而是构建 func_wrapper
函数的自定义版本,"remembers" 它应该使用 [=21] 调用什么函数=].
如果您为 my_get_text1
和 my_get_text2
两次传入相同的函数,您将对 func_wrapper.func_closure
位、内存地址和 [=25 的所有内容拥有完全相同的东西=], 因为它是相同的功能。 (当您实际使用可能不同的参数调用它时减去。)
装饰器:
正如您所指出的,装饰器只是一个可调用函数,它接受一个函数作为参数,returns 一个替换函数。在您的代码中,这将分别是 p_decorator
和 func_wrapper
。
如果你想以 OOP 的方式考虑这个......你可以将 p_decorate
视为函数 func_wrapper
的构造函数,其中 func 充当私有成员变量/属性,因为你或多或少基本上构建了一个带有硬编码参数的函数 func
.
为什么 returns 它的作用:
希望以上都是正确的+有意义...然后,它returns你看到的值,因为你已经通过了get_text
函数"remembered"并且因为func_wrapper
被返回......你正在调用 func_wrapper(arg)
参数 John
现在在这个里面...... func_wrapper
returns 以下:
"<p>{0}</p>".format(func(name))"
func
为 get_text
。因此,get_text
被称为 returns...
"lorem ipsum, {0} dolor sit amet".format(name)
然后在开始和结束 p
标记之间进行格式化,然后返回。
您可以拥有多层嵌套函数,并且与 python 中的几乎所有内容一样,它一直是海龟。
为什么还要使用装饰器?
在这个例子中,我认为你是对的,我只使用第二个函数,因为这是一个非常无用的例子。
但是,请考虑更具体的事情。我将使用一个常见的 django 装饰器作为我头脑中的例子。即使您不熟悉 Django,这仍然有意义。
在 django 中,您有呈现网页的函数/视图,有时您可能希望要求用户登录才能查看页面。
现在,如果您必须为每个函数编写自定义逻辑怎么办。
那就太糟糕了。相反,有一个名为 @login_required
的漂亮装饰器,您只需将它放在您想要此功能的函数的顶部,您就可以节省大量时间/重复代码,因为这个装饰器将这个自定义逻辑包装在您的函数周围已经应用到。
装饰器主要用于扩展/自定义功能而无需重新编码的情况。
比函数更进一步....如果您想将其应用于 class
的方法怎么办?也许他们都符合某些标准?必须为每个方法都这样做会有点乏味并且可能很烦人。您可以编写一个装饰器来包装 class 并将其自动神奇地应用到每个函数,而不是用 @decorator_name
包装每个方法。
咆哮 - 为什么人们说 'a decorator is a function that returns another function'?这个定义没有意义,因为如果装饰器就是这样,为什么不只使用第二个函数而不用第一个呢? - 结束咆哮
幸运的是,我在这里找到了一个更合理的定义: http://thecodeship.com/patterns/guide-to-python-function-decorators/
不幸的是,我还是不明白这些例子,比如这个:
def get_text(name):
return "lorem ipsum, {0} dolor sit amet".format(name)
def p_decorate(func):
def func_wrapper(name):
return "<p>{0}</p>".format(func(name))
return func_wrapper
my_get_text = p_decorate(get_text)
print my_get_text("John")
#Outputs "<p>lorem ipsum, John dolor sit amet</p>"
请注意,post 已有两年多了,作者尚未对任何评论做出回应。
这是我的问题:为什么不输出
"<p>John</p>"
还是错误?整个字符串如何进入 p 标签而不只是名称?
编辑:我刚刚发现您链接了一篇文章,从字面上逐步解释了装饰器是什么...但是已经输入了,所以...
Python 中有一个称为闭包/函数闭包的特性。
自从我试图解释/理解闭包/装饰器在较低级别发生的事情以来已经有一段时间了,所以这实际上可能是错误的。
函数func_wrapper每次调用p_decorate
时都会被重新定义,func_wrapper会记住包含的内容 命名空间在定义时的样子。
什么意思:
例如,假设您有一些嵌套在 p_decorate
中的外部变量,您会期望这会引发错误,因为当 func_wrapper
被调用并尝试使用这个变量,但它不会,因为封闭的命名空间是 "remembered"
在 python 3 中是 __closure__
,在 python 2 中是 func_closure
以下。
def get_text(name):
return "lorem ipsum, {0} dolor sit amet".format(name)
def p_decorate(func):
def func_wrapper(name):
return "<p>{0}</p>".format(func(name)) #Cached result
print(func_wrapper.func_closure)
return func_wrapper
my_get_text1 = p_decorate(get_text)
my_get_text2 = p_decorate(get_text2)
func_closure 东西:
my_get_text1 >>> (<cell at 0x*: function object at 0x*>,)
my_get_text2 >>> (<cell at 0x(different address): function object at (diff address)>,)
我们没有将不同的函数传递给 func_wrapper
函数,而是构建 func_wrapper
函数的自定义版本,"remembers" 它应该使用 [=21] 调用什么函数=].
如果您为 my_get_text1
和 my_get_text2
两次传入相同的函数,您将对 func_wrapper.func_closure
位、内存地址和 [=25 的所有内容拥有完全相同的东西=], 因为它是相同的功能。 (当您实际使用可能不同的参数调用它时减去。)
装饰器:
正如您所指出的,装饰器只是一个可调用函数,它接受一个函数作为参数,returns 一个替换函数。在您的代码中,这将分别是 p_decorator
和 func_wrapper
。
如果你想以 OOP 的方式考虑这个......你可以将 p_decorate
视为函数 func_wrapper
的构造函数,其中 func 充当私有成员变量/属性,因为你或多或少基本上构建了一个带有硬编码参数的函数 func
.
为什么 returns 它的作用:
希望以上都是正确的+有意义...然后,它returns你看到的值,因为你已经通过了get_text
函数"remembered"并且因为func_wrapper
被返回......你正在调用 func_wrapper(arg)
参数 John
现在在这个里面...... func_wrapper
returns 以下:
"<p>{0}</p>".format(func(name))"
func
为 get_text
。因此,get_text
被称为 returns...
"lorem ipsum, {0} dolor sit amet".format(name)
然后在开始和结束 p
标记之间进行格式化,然后返回。
您可以拥有多层嵌套函数,并且与 python 中的几乎所有内容一样,它一直是海龟。
为什么还要使用装饰器?
在这个例子中,我认为你是对的,我只使用第二个函数,因为这是一个非常无用的例子。
但是,请考虑更具体的事情。我将使用一个常见的 django 装饰器作为我头脑中的例子。即使您不熟悉 Django,这仍然有意义。
在 django 中,您有呈现网页的函数/视图,有时您可能希望要求用户登录才能查看页面。
现在,如果您必须为每个函数编写自定义逻辑怎么办。
那就太糟糕了。相反,有一个名为 @login_required
的漂亮装饰器,您只需将它放在您想要此功能的函数的顶部,您就可以节省大量时间/重复代码,因为这个装饰器将这个自定义逻辑包装在您的函数周围已经应用到。
装饰器主要用于扩展/自定义功能而无需重新编码的情况。
比函数更进一步....如果您想将其应用于 class
的方法怎么办?也许他们都符合某些标准?必须为每个方法都这样做会有点乏味并且可能很烦人。您可以编写一个装饰器来包装 class 并将其自动神奇地应用到每个函数,而不是用 @decorator_name
包装每个方法。