函数括号问题
import timedef func_one(func_1) :
def func_two(func_2):
start = time.time()
print('start!')
func_2()
stop = time.time()
print('stop!')
print(f'{func_1}:{(stop-start):0.4f}秒')
return func_two
@func_one('程序运行时间为')
def func():
time.sleep(2)
print('func函数运行中 ')
func() #TypeError: 'NoneType' object is not callable
func
如果函数func加上括号就报错。“TypeError: 'NoneType' object is not callable”但程序结果能正常显示
如果函数func不加上括号就能正常运行。
定义和调用函数后面要加上括号,这里为什么不加括号反正是能正常运行。
谢谢 这是一个有趣的问题!主要涉及到了装饰器的使用。我们先解释一下 `@func_one('程序运行时间为')` 这个装饰器的作用,以及为什么会出现这个问题。
### 代码问题解析
首先,我们看一下装饰器的定义:
import time
def func_one(func_1):
def func_two(func_2):
start = time.time()
print('start!')
func_2()
stop = time.time()
print('stop!')
print(f'{func_1}:{(stop-start):0.4f}秒')
return func_two
@func_one('程序运行时间为')
def func():
time.sleep(2)
print('func函数运行中 ')
装饰器函数 `func_one` 接受一个参数 `func_1`,并返回一个新的函数 `func_two`。`func_two` 是一个装饰器函数,它接受 `func_2` 作为参数。注意,这里的 `func_2` 就是被装饰的函数 `func`。
当你执行 `func()` 时,实际上调用的是 `func_two` 函数,而 `func_two` 函数中调用了 `func_2`。由于 `func_2()` 是在 `func_two` 内部被调用的,所以能够正常输出。而如果你不加括号,只是 `func` 的名称,那么不会实际调用到 `func_two` 函数。
### 出错原因
当你执行 `func()` 时:
1. 装饰器 `@func_one('程序运行时间为')` 实际上将 `func` 替换成了 `func_two`。
2. `func_two` 函数被返回并赋值给 `func`。
3. 但由于你没有将最终的 `func_two` 进行正确调用,导致程序逻辑出了问题。
所以,在调用 `func()` 时,会实际执行 `func_two` 函数,但如果不加括号,则不会执行 `func_two` 而只是引用 `func_two` 这个对象。
### 解决方法
为了让代码更清晰、逻辑更正确,我们可以修改一下代码,使其更易于理解:
import time
def func_one(description):
def decorator(func):
def wrapper():
start = time.time()
print('start!')
func()
stop = time.time()
print('stop!')
print(f'{description} {(stop-start):0.4f}秒')
return wrapper
return decorator
@func_one('程序运行时间为')
def func():
time.sleep(2)
print('func函数运行中 ')
# 这里调用func函数,实际上是调用func_one装饰器后的wrapper函数
func()
在这个代码中:
1. `func_one` 返回一个真正的装饰器 `decorator`。
2. `decorator` 装饰 `func` 函数,并返回一个 `wrapper` 函数。
3. 最终,`func` 实际上被替换成 `wrapper`,所以调用 `func()` 相当于调用 `wrapper()`。
这样,代码的逻辑就更清晰了,再调用 `func()` 时不会产生困惑。
希望这个解释和改进后的代码能帮助你更好地理解装饰器的工作原理!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2024-6-18 22:50
这是一个有趣的问题!主要涉及到了装饰器的使用。我们先解释一下 `@func_one('程序运行时间为')` 这个装饰 ...
谢谢,看了三、四遍,基本上懂了一点了,谢谢你,年纪大了,自学自己爱好的事,个人感觉确实不容易。这里的大师们真的不错,有问必答。十分感谢。
页:
[1]