python - 我无法访问 Cog 内的类方法中的类参数
问题描述
我最近开始尝试使用 discord.py 进行机器人开发,并且一直在为某种情况而苦苦挣扎,在这种情况下,我在 Cogs 中使用了常规的类方法。这是一个示例,机器人应向“-hello”命令回复“hello there”:
import discord
from discord.ext import commands
import os
from dotenv import load_dotenv
load_dotenv()
class TestCog(commands.Cog):
def __init__(self):
super().__init__()
self.testMessage = "hello there"
@commands.command(name = 'hello')
async def hello(self, ctx):
await self.sayHello(ctx)
@classmethod
async def sayHello(self, ctx):
await ctx.send(self.testMessage)
token = os.getenv("botToken")
intents = discord.Intents().all()
client = discord.Client(intents = intents)
bot = commands.Bot(command_prefix='-', intents=intents)
bot.add_cog(TestCog())
if __name__ == "__main__":
bot.run(token)
如果我运行此代码,然后使用命令“-hello”,我会收到错误消息:
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: type object 'TestCog' has no attribute 'testMessage'
我认为这是因为常规的类方法可能在 Cog 中不起作用,所以我也尝试这样写:
import discord
from discord.ext import commands
import os
from dotenv import load_dotenv
load_dotenv()
class TestBot(commands.Bot):
def __init__(self, command_prefix, intents):
super().__init__(command_prefix=command_prefix, intents=intents)
self.testMessage = "hello there"
self.add_cog(TestCog(self))
@classmethod
async def sayHello(self, ctx):
await ctx.send(self.testMessage)
class TestCog(commands.Cog):
def __init__(self, bot) -> None:
super().__init__()
self.bot = bot
@commands.command(name = 'hello')
async def hello(self, ctx):
await self.bot.sayHello(ctx)
token = os.getenv("botToken")
intents = discord.Intents().all()
client = discord.Client(intents = intents)
bot = TestBot('-', intents)
if __name__ == "__main__":
bot.run(token)
这也给出了同样的错误。但是,如果我不使用方法,并将其写为:
import discord
from discord.ext import commands
import os
from dotenv import load_dotenv
load_dotenv()
class TestBot(commands.Bot):
def __init__(self, command_prefix, intents):
super().__init__(command_prefix=command_prefix, intents=intents)
self.add_cog(TestCog(self))
class TestCog(commands.Cog):
def __init__(self, bot) -> None:
super().__init__()
self.testMessage = 'hello there'
@commands.command(name = 'hello')
async def hello(self, ctx):
await ctx.send(self.testMessage)
token = os.getenv("botToken")
intents = discord.Intents().all()
client = discord.Client(intents = intents)
bot = TestBot('-', intents)
if __name__ == "__main__":
bot.run(token)
它工作正常。它也适用于我不引用 self 的前两种情况,例如await ctx.send('hello there')
代替 await ctx.send(self.testMessage)
. 但是,不能在命令中使用方法有点麻烦,所以我会绕过前两个场景吗?
解决方案
@classmethod
装饰器不适用于在类中定义方法。这意味着当调用此方法时,我们将类作为第一个参数而不是该类的实例传递(就像我们通常对方法所做的那样)。这意味着您可以在该方法而不是特定实例中使用类及其属性。类中的普通函数是您要实际使用的类实例方法(普通/默认方法)
您的代码不起作用,因为 self 实际上是类本身而不是实例(因为它是类方法)。并且您无法访问实例变量,因为它不是实例。
要解决此问题,您应该删除 classmethod 装饰器以使其成为函数的普通方法
class TestCog(commands.Cog):
def __init__(self):
super().__init__()
self.testMessage = "hello there"
@commands.command(name = 'hello')
async def hello(self, ctx):
await self.sayHello(ctx)
async def sayHello(self, ctx):
await ctx.send(self.testMessage)
推荐阅读
- javascript - 如何创建 React formik 表单的 Jest 快照
- node.js - 无法为 Angular 构建新包
- elasticsearch - 通过 Elasticsearch 结果分页时重复的内容
- html - CSS 样式未应用于 HTML 文档上的特定 div
- azure - Azure 数据工厂 SQL Server 连接错误代码 9056
- javascript - 未捕获的错误:无法在使用 jQuery 初始化之前调用对话框上的方法
- java - android生成7位校验和以将数据传递给蓝牙模块
- python - Python __ror__ 没有初始化类
- python - Python更新类变量
- c# - asp net core 2中的DataAnnotations本地化