如何解决显示装饰器结果的错误?
How do I solve an error in showing the result of a decorator?
我正在学习Python3,想写一个简单的代码来学习装饰器。我试过 运行 这个代码:
def makebold(fn):
def wrapped():
return '<b>' + str(fn) + '</b>'
return wrapped()
def makeitalic(fn):
def wrapped():
return '<i>' + str(fn) + '</i>'
return wrapped()
@makebold
@makeitalic
def hello():
return "Hello World"
print(hello())
但我收到以下错误:
Traceback (most recent call last):
File "E:\Msn Folder\Python\Projects\PythonSamplesByMsn Functions\D03_Decorator01.py", line 29, in <module>
print(hello())
TypeError: 'str' object is not callable
我做错了什么?我该如何纠正?
您必须删除 return wrapped()
末尾的 ()
并将 str(fn)
更改为 str(fn())
因为必须调用 fn
函数对象。
使用这个
def makebold(fn):
def wrapped():
return '<b>' + str(fn()) + '</b>'
return wrapped
def makeitalic(fn):
def wrapped():
return '<i>' + str(fn()) + '</i>'
return wrapped
@makeitalic
@makebold
def hello():
return "Hello World"
print(hello())
<i><b>Hello World</b></i>
你应该试试这个:
def makebold(fn):
def wrapped():
return '<b>' + str(fn()) + '</b>'
return wrapped
def makeitalic(fn):
def wrapped():
return '<i>' + str(fn()) + '</i>'
return wrapped
@makebold
@makeitalic
def hello():
return "Hello World"
print(hello())
你应该在装饰器方法中调用包装函数。
装饰器方法必须return一个函数对象。
首先,请注意
@bar
def foo():
...
只是 shorthand 用于:
foo = bar(foo)
即您用函数本身调用bar
的结果替换函数。因此,在此之后,foo('baz')
实际上是 bar(foo)('baz')
,即试图调用 由 bar
编辑的 return。
正是出于这个原因,用作装饰器的函数的 return 值 本身必须是可调用的 。但是,您的 "decorators" return strings 是 not 可调用的。如果我们定义:
def bar(func):
return 'bar'
那么很明显 bar(foo)('baz')
变成了 'bar'('baz')
,导致您看到的错误:
TypeError: 'str' object is not callable
你的装饰器 return 字符串,因为你 调用 wrapped
,因此 return 不管它 return 是什么(一个字符串):
return wrapped()
# ^ note parentheses in your version
而不是return函数本身:
return wrapped
# ^ and their absence when fixed
第二个错误是在 wrapped
函数中,您有:
return '<b>' + str(fn) + '</b>'
这里你遇到了与上面 相反的问题 - 你正在制作一个 函数本身 的字符串,而不是使用字符串 the函数 returns。
记住装饰器是用它装饰的函数作为参数调用的,即装饰器内部的 fn
指的是 被装饰的函数 (例如 hello
对于 makebold
)。你真正想要包裹标签的是 what the wrapped function returns (它已经是一个字符串,所以你不需要调用 str
:
return '<i>' + fn() + '</i>'
# ^ again, parentheses are important!
您也可以使用适当的字符串格式,而不是 +
连接:
return '<i>{}</i>'.format(fn())
我正在学习Python3,想写一个简单的代码来学习装饰器。我试过 运行 这个代码:
def makebold(fn):
def wrapped():
return '<b>' + str(fn) + '</b>'
return wrapped()
def makeitalic(fn):
def wrapped():
return '<i>' + str(fn) + '</i>'
return wrapped()
@makebold
@makeitalic
def hello():
return "Hello World"
print(hello())
但我收到以下错误:
Traceback (most recent call last):
File "E:\Msn Folder\Python\Projects\PythonSamplesByMsn Functions\D03_Decorator01.py", line 29, in <module>
print(hello())
TypeError: 'str' object is not callable
我做错了什么?我该如何纠正?
您必须删除 return wrapped()
末尾的 ()
并将 str(fn)
更改为 str(fn())
因为必须调用 fn
函数对象。
使用这个
def makebold(fn):
def wrapped():
return '<b>' + str(fn()) + '</b>'
return wrapped
def makeitalic(fn):
def wrapped():
return '<i>' + str(fn()) + '</i>'
return wrapped
@makeitalic
@makebold
def hello():
return "Hello World"
print(hello())
<i><b>Hello World</b></i>
你应该试试这个:
def makebold(fn):
def wrapped():
return '<b>' + str(fn()) + '</b>'
return wrapped
def makeitalic(fn):
def wrapped():
return '<i>' + str(fn()) + '</i>'
return wrapped
@makebold
@makeitalic
def hello():
return "Hello World"
print(hello())
你应该在装饰器方法中调用包装函数。
装饰器方法必须return一个函数对象。
首先,请注意
@bar
def foo():
...
只是 shorthand 用于:
foo = bar(foo)
即您用函数本身调用bar
的结果替换函数。因此,在此之后,foo('baz')
实际上是 bar(foo)('baz')
,即试图调用 由 bar
编辑的 return。
正是出于这个原因,用作装饰器的函数的 return 值 本身必须是可调用的 。但是,您的 "decorators" return strings 是 not 可调用的。如果我们定义:
def bar(func):
return 'bar'
那么很明显 bar(foo)('baz')
变成了 'bar'('baz')
,导致您看到的错误:
TypeError: 'str' object is not callable
你的装饰器 return 字符串,因为你 调用 wrapped
,因此 return 不管它 return 是什么(一个字符串):
return wrapped()
# ^ note parentheses in your version
而不是return函数本身:
return wrapped
# ^ and their absence when fixed
第二个错误是在 wrapped
函数中,您有:
return '<b>' + str(fn) + '</b>'
这里你遇到了与上面 相反的问题 - 你正在制作一个 函数本身 的字符串,而不是使用字符串 the函数 returns。
记住装饰器是用它装饰的函数作为参数调用的,即装饰器内部的 fn
指的是 被装饰的函数 (例如 hello
对于 makebold
)。你真正想要包裹标签的是 what the wrapped function returns (它已经是一个字符串,所以你不需要调用 str
:
return '<i>' + fn() + '</i>'
# ^ again, parentheses are important!
您也可以使用适当的字符串格式,而不是 +
连接:
return '<i>{}</i>'.format(fn())