You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 07:47:31