我正在使用discord.py模块尝试设置机器人。在模块中编写命令如下:
@bot.command()
async def test_function(ctx):
await ctx.send('test')
我想将其他装饰器应用于这些命令功能之一,但是只需执行以下操作即可:
def second_decorator(func):
def wrapper():
print('wrapper activated!')
func()
return wrapper
@second_decorator
@bot.command()
async def test_function...
似乎不起作用。据我所知,第二个装饰器根本没有生效-“包装器已激活!”永远不会打印。
在TypeError: Callback must be a coroutine.
中切换两个结果的顺序,从我在多个装饰器上看到的文档来看,这都不是正确的格式。
答案 0 :(得分:2)
通常在装饰函数时这样做是因为要在函数上调用装饰器,并使用装饰器的结果而不是函数定义。 bot.command
可以做到这一点,但更重要的是,它会将功能注册为机器人内部的回调。伪代码版本看起来像
def command(self, callback, **options):
if not valid(callback):
raise error
comm = Command(callback, **options)
self.commands[comm.name] = comm
return comm
因此,在调用第二个装饰器时(装饰器从下到上评估),该回调已在该漫游器中注册。 test_function
将引用wrapped
,但向漫游器注册的回调将不会。
您无法以其他方式订购装饰器,因为command()
要求其参数(second_decorator的返回值wrapped
)为协程(async def
函数) 。这是我写second_decorator
def second_decorator(coro):
print("function wrapped")
@functools.wrap(coro) # Important to preserve name because `command` uses it
async def wrapper(*args, **kwargs):
print('wrapped function called')
return await coro(*args, **kwargs)
return wrapper