Python中‘NoneType object is not callable’错误的原因及解决建议
为什么第二种Python代码会抛出"NoneType object is not callable"错误?
先看你给出的两段代码:
第一段可正常运行的代码
#firstcode def decor(func): def wrap(): print("=============") func() print("=============") return wrap def print_text(): print("Hello world!") print_text = decor(print_text) print_text()
第二段报错的代码
#secondcode def wrap(func): print("=============") func() print("=============") def print_text(): print("Hello world!") print_text = wrap(print_text) print_text()
核心原因分析
第一段代码是标准的装饰器实现:
decor函数内部定义了wrap函数,最后返回的是这个wrap函数对象。当你执行print_text = decor(print_text)时,print_text被替换成了wrap函数,之后调用print_text()本质是调用wrap(),而wrap()会执行原print_text的逻辑,同时加上前后的分隔线打印,完全符合预期。第二段代码的问题出在
wrap函数的返回值上:Python中如果函数没有显式写return语句,默认会返回None。当你执行print_text = wrap(print_text)时,wrap(print_text)会立刻执行(此时已经打印了分隔线和"Hello world!"),然后把返回的None赋值给了print_text。之后你调用print_text(),相当于试图调用None这个非可调用对象,自然就抛出了NoneType object is not callable的错误。
解决建议
- 如果想实现类似第一段的装饰器效果,必须让负责增强功能的函数返回一个新的可调用函数(比如嵌套函数),而不是直接执行逻辑。比如可以把第二段的
wrap改成类似第一段的嵌套结构:
def decor(func): def wrap(): print("=============") func() print("=============") return wrap def print_text(): print("Hello world!") print_text = decor(print_text) print_text()
- 如果只是想临时给
print_text增加一次额外打印,不需要替换原函数,直接调用wrap(print_text)即可,不用赋值回print_text:
def wrap(func): print("=============") func() print("=============") def print_text(): print("Hello world!") wrap(print_text) # 直接调用,不会改变原print_text的指向
内容的提问来源于stack exchange,提问作者mfcaglar
相关产品推荐
相关产品推荐

