鱼C论坛

 找回密码
 立即注册
查看: 144|回复: 2

[已解决]函数括号问题

[复制链接]
发表于 2024-6-18 22:49:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
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() #TypeError: 'NoneType' object is not callable
func

如果函数func加上括号就报错。“TypeError: 'NoneType' object is not callable”但程序结果能正常显示
如果函数func不加上括号就能正常运行。

定义和调用函数后面要加上括号,这里为什么不加括号反正是能正常运行。

谢谢
最佳答案
2024-6-18 22:50:00
这是一个有趣的问题!主要涉及到了装饰器的使用。我们先解释一下 `@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 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-6-18 22:50:00 | 显示全部楼层    本楼为最佳答案   
这是一个有趣的问题!主要涉及到了装饰器的使用。我们先解释一下 `@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 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-6-19 09:18:51 | 显示全部楼层
FishC 发表于 2024-6-18 22:50
这是一个有趣的问题!主要涉及到了装饰器的使用。我们先解释一下 `@func_one('程序运行时间为')` 这个装饰 ...

谢谢,看了三、四遍,基本上懂了一点了,谢谢你,年纪大了,自学自己爱好的事,个人感觉确实不容易。这里的大师们真的不错,有问必答。十分感谢。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-22 20:16

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表