我花了至少一天的时间试图找到问题的答案,包括至少花几个小时与嵌套装饰器混在一起,但我似乎无法弄清楚。
我正在使用 Discord.py,它是
commands.check
“装饰器生成器”,但我认为问题(可能是解决方案)可能并不是真正特定于 Discord.py 的。
问题陈述如下:
我想在
check
上声明一个 Discord.py Cog
,但需要访问 Cog 的实例来执行一些数据获取以解决检查问题。
现在,Discord.py 声明检查的语法是在给定谓词函数的情况下调用 commands.check 函数,该谓词函数又返回一个可应用于任何 Cog 方法的装饰器,例如
def custom_check():
async def predicate(ctx):
# I'll need to do some data fetching here...
return True
return commands.check(predicate)
class MyCog(commands.Cog):
@commands.command()
@custom_check()
async func(self, ctx):
pass
async def some_data_fetching():
pass
我一直在想办法解决这个问题,但无法解决这个问题。我一直在探索如何创建一个可以访问 self 的包装闭包,但是
predicate
函数——在任何方法被调用并且 self 可用之前,需要先调用 commands.check
(并将谓词传递给它)。def custom_check():
async def predicate(ctx):
print('predicate called')
return False
check_decorator = commands.check(predicate)
def custom_decorator(f):
async def wrapper(self, *args, **kwargs):
return await f(self, *args, **kwargs)
return wrapper
return lambda f: check_decorator(custom_decorator(f))
非常感谢任何帮助或建议。
解决方案:使用
ctx.cog
或ctx.args
def custom_check():
async def predicate(ctx):
data = await ctx.cog.some_data_fetching()
return data.checks_out
return commands.check(predicate)
我决定仔细查看提供的上下文 (
ctx
) 并意识到它同时具有 args 属性(具有传递给命令调用的参数,包括 self
)以及 cog
属性引用调用的命令所在的 cog。他们中的任何一个都可以让我做我需要做的事。
感谢您成为我的听众。