Discord机器人嵌套函数调用异常:倒计时输出无法正常触发
修复Discord机器人倒计时装饰器的嵌套调用问题
原代码核心问题分析
- 装饰器返回逻辑错误:原代码
return wrapper("*args, **kwargs")直接调用了wrapper并返回结果,而非返回wrapper函数本身。这导致装饰器在定义阶段就执行了一次,被装饰的countfunc最终变成了wrapper的返回值(即None)。 - 计数器每次被重置:
wrapper内部每次调用都重新设置wrapper.counter = 3,导致计数器永远只会从3减到2,无法实现从3到0的递减逻辑。 - 被装饰函数参数冗余:
@count def countfunc(wrapper):不需要接收wrapper参数,装饰器包装后的函数调用时不会传入该参数。 - 外部调用方式错误:
print(countfunc)是打印函数对象(此时已为None),而非调用触发逻辑的countfunc()。
修复后的代码
def count(countfunc): # 将计数器初始化移到wrapper外部,确保仅在装饰器应用时初始化一次 wrapper.counter = 3 wrapper.start = 3 def wrapper(*args, **kwargs): # 可选:限制计数器到0后不再继续递减 if wrapper.counter <= 0: print("Already banned, no more warnings to issue") return countfunc(*args, **kwargs) wrapper.counter -= 1 if wrapper.counter == 0: print(f"has ran out of warnings & is now banned on the server for 1 day") else: print(f"has {wrapper.counter} warnings left") return countfunc(*args, **kwargs) # 返回wrapper函数本身,而非调用结果 return wrapper # 被装饰函数无需额外参数 @count def countfunc(): return # 调用函数触发倒计时逻辑 countfunc() countfunc() countfunc() countfunc()
修复说明
- 修正装饰器返回值:将
return wrapper("*args, **kwargs")改为return wrapper,让装饰器正确为countfunc包装逻辑,而非立即执行并返回None。 - 调整计数器初始化位置:把
wrapper.counter = 3移到wrapper函数外部,确保计数器仅初始化一次,每次调用countfunc()时持续递减。 - 移除冗余参数:删除
countfunc的wrapper参数,匹配装饰器的调用逻辑。 - 正确触发函数逻辑:使用
countfunc()调用函数,而非打印函数对象,触发wrapper内的倒计时输出。
输出结果
has 2 warnings left has 1 warnings left has ran out of warnings & is now banned on the server for 1 day Already banned, no more warnings to issue
内容的提问来源于stack exchange,提问作者Ben Robinson
相关产品推荐
相关产品推荐

