iT邦幫忙

0

【Python】函數與繼承問題

我想要在外部直接用函數來呼叫其中的_join元素
MusicBot-by vbe0201|GitHub

目前的程式碼:

import discord
from discord.ext import commands
from music_bot_example import Music

def reply_handler(bot, ctx):
    obj1 = Music(bot)
    class obj2(obj1, ctx):
        pass
    obj1.bot.loop.create_task(obj1.core_join(obj2))

class Chat(Cog_Extension):
    @commands.Cog.listener()
    async def on_message(self, ctx):
        reply_handler(self.bot, ctx)

def setup(bot):
    bot.add_cog(Chat(bot))

並且將 _join替換成一個裸函數以供呼叫:

async def core_join(self, ctx: commands.Context):
        destination = ctx.author.voice.channel
        if ctx.voice_state.voice:
            await ctx.voice_state.voice.move_to(destination)
            return

        ctx.voice_state.voice = await destination.connect()

    @commands.command(name='join', invoke_without_subcommand=True)
    async def _join(self, ctx: commands.Context):
        """Joins a voice channel."""
        return self.core_join(ctx)

error

in reply_handler
    class Object(Music(bot), ctx):
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

請各位高手指點 Orz

marlin12 iT邦研究生 5 級 ‧ 2020-11-29 14:17:40 檢舉
_cmd不是CLASSa的static函数,怎麼可能直接用CLASSa._cmd來呼叫?!
應該是
objA = CLASSa( bot )
objA._cmd( ctx )
還是不行,那我改用繼承,而他同時要包含Music和ctx的屬性
marlin12 iT邦研究生 5 級 ‧ 2020-11-29 20:42:57 檢舉
不可能把Chat的Context,當作Music的Context來用。
其實discord.py的官網是有一個Cog呼叫另一個Cog的例子,但是它也避開Context這個問題。
https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html (看Using Cogs那個章節)

1 個回答

2
marlin12
iT邦研究生 5 級 ‧ 2020-11-29 20:17:00

不知這樣是否可行

class Music(commands.Cog):
  ...   ...   ...
  async def invoke_join(self):
    await self.bot.get_command('_join').callback()
class Chat(Cog_Extension):
  ...   ...   ...
  async def bkgd_task(self):
    await self.bot.wait_until_ready()
    music = self.bot.get_cog('Music')
    if music is not None:
      await music.invoke_join()

  @commands.Cog.listener()
  async def on_message(self, ctx):
    self.bot.loop.create_task(bkgd_task())

用callback只解決了呼叫的問題,和調用裸函數的效果相同,且比較複雜,因為要用Cog.get_commands而非bot.get_command(會回傳None),且_join還是需要一個參數,我將ctx做為參數傳入後遇到了問題:

AttributeError: 'Message' object has no attribute 'voice_state'

感覺就是要多重繼承,但又會進到上面問的問題。

我要發表回答

立即登入回答