如何在Discord.py中从主命令向子命令传递参数
没问题,这在Discord.py里完全可以实现,有两种常用的方案来完成你想要的效果——让主命令先把频道标识符转换成对象,再传递给子命令。我给你详细拆解一下:
方法一:利用上下文(ctx)的自定义属性
这种方法是把转换好的频道对象存到ctx的自定义属性里,子命令直接从上下文里取这个对象就行,不用再自己处理参数。
完整代码示例:
from discord.ext import commands import discord class YourCog(commands.Cog): def __init__(self, bot): self.bot = bot @commands.group(name="channel", invoke_without_command=True) async def channel_group(self, ctx, *, channel_identifier): # 把频道名称/ID转换为频道对象 try: # 优先尝试按ID查找(支持服务器内和跨服务器频道) channel_obj = await self.bot.fetch_channel(int(channel_identifier)) except ValueError: # 如果不是数字ID,就按名称在当前服务器查找 channel_obj = discord.utils.get(ctx.guild.channels, name=channel_identifier) if not channel_obj: await ctx.send("抱歉,找不到对应的频道!") return # 将转换好的频道对象存入ctx的自定义属性 ctx.target_channel = channel_obj # 如果用户只输入了主命令没带子命令,提示可用子命令 if ctx.invoked_subcommand is None: await ctx.send("请指定子命令:`get_mention` 或 `get_id`") @channel_group.command(name="get_mention") async def channel_get_mention(self, ctx): # 直接从ctx里取之前存好的频道对象 await ctx.send(ctx.target_channel.mention) @channel_group.command(name="get_id") async def channel_get_id(self, ctx): await ctx.send(str(ctx.target_channel.id)) # 别忘了注册Cog def setup(bot): bot.add_cog(YourCog(bot))
关键说明:
- 给主命令加上
invoke_without_command=True,确保当用户只输入!channel(不带子命令)时,主命令的代码会执行并给出提示。 - 转换逻辑里先尝试按ID查找(用
fetch_channel),失败再按名称查找(用discord.utils.get),覆盖了两种输入场景。 - 把频道对象存在
ctx.target_channel里,子命令直接调用这个属性即可,不用再处理参数。
方法二:手动调用子命令并传递参数
如果你更倾向于直接给子命令传参,可以在主命令里获取到被调用的子命令,然后手动调用它并把频道对象传进去。
完整代码示例:
from discord.ext import commands import discord class YourCog(commands.Cog): def __init__(self, bot): self.bot = bot @commands.group(name="channel", invoke_without_command=True) async def channel_group(self, ctx, *, channel_identifier): # 同样的频道转换逻辑 try: channel_obj = await self.bot.fetch_channel(int(channel_identifier)) except ValueError: channel_obj = discord.utils.get(ctx.guild.channels, name=channel_identifier) if not channel_obj: await ctx.send("抱歉,找不到对应的频道!") return # 获取用户调用的子命令 subcommand = ctx.invoked_subcommand if subcommand: # 手动调用子命令,把频道对象作为参数传进去 await subcommand(ctx, channel_obj) else: await ctx.send("请指定子命令:`get_mention` 或 `get_id`") @channel_group.command(name="get_mention") async def channel_get_mention(self, ctx, channel_obj): await ctx.send(channel_obj.mention) @channel_group.command(name="get_id") async def channel_get_id(self, ctx, channel_obj): await ctx.send(str(channel_obj.id)) def setup(bot): bot.add_cog(YourCog(bot))
关键说明:
- 子命令需要保留
channel_obj参数,因为主命令会手动把对象传进来。 - 用
ctx.invoked_subcommand获取到用户触发的子命令,然后直接调用它并传递参数,这种方式更接近你提到的pass思路。
两种方法都能实现你的需求,你可以根据自己的代码习惯选择。另外记得处理频道找不到的情况,避免后续代码报错哦!
内容的提问来源于stack exchange,提问作者CircuitSacul
相关产品推荐
相关产品推荐

