Что является хорошей альтернативой тому, как я пытаюсь использовать on_message [duplicate]

Виртуальный конструктор невозможен, но возможен виртуальный деструктор. Проведем эксперимент ....

#include <iostream>

using namespace std;

class Base
{
public:
    Base(){
        cout << "Base Constructor Called\n";
    }
    ~Base(){
        cout << "Base Destructor called\n";
    }
};

class Derived1: public Base
{
public:
    Derived1(){
        cout << "Derived constructor called\n";
    }
    ~Derived1(){
        cout << "Derived destructor called\n";
    }
};

int main()
{
    Base *b = new Derived1();
    delete b;
}

Вышеприведенный код выводит следующее:

Base Constructor Called
Derived constructor called
Base Destructor called

Построение производного объекта следует за правилом построения, но когда мы удаляем «b "указатель (базовый указатель) мы обнаружили, что только деструктор базы является вызовом. Но этого не должно быть. Чтобы сделать правильную вещь, мы должны сделать базовый деструктор виртуальным. Теперь посмотрим, что произойдет в следующем:

#include <iostream>

using namespace std;

class Base
{ 
public:
    Base(){
        cout << "Base Constructor Called\n";
    }
    virtual ~Base(){
        cout << "Base Destructor called\n";
    }
};

class Derived1: public Base
{
public:
    Derived1(){
        cout << "Derived constructor called\n";
    }
    ~Derived1(){
        cout << "Derived destructor called\n";
    }
};

int main()
{
    Base *b = new Derived1();
    delete b;
}

Выход изменился следующим образом:

Base Constructor Called
Derived constructor called
Derived destructor called
Base Destructor called

Итак, уничтожение базового указателя (который принимает выделение на производном объекте! ) следуют за правилом уничтожения, т. е. сначала выведенным потом базой. С другой стороны, для конструктора нет ничего похожего на виртуальный конструктор.

1
задан abccd 8 July 2018 в 15:59
поделиться

2 ответа

Это невозможно с помощью нативного Client

У вас может быть только один on_message, если у вас есть несколько, для on_message. Вам просто нужно объединить три on_message.

import discord

client = discord.Client()

@client.event
async def on_message(message):
    print("in on_message #1")
    print("in on_message #2")
    print("in on_message #3")

client.run("TOKEN")

Как и любая переменная / функция Python (если декоратор не сохраняет вашу функцию, @client.event делает это, сохраняя только самый последний обратный вызов) , если несколько имен одинаковы, последнее будет сохранено, а все остальные будут перезаписаны.

Это простой пример, который я написал, чтобы дать вам общее представление о том, как события в работе discord.py (обратите внимание: фактический код не совсем такой, как он переписан и значительно уменьшен).

class Client:
    def event(self, func):               
        if func.__name__ == "on_message":
            self.on_message_handle = func
            return func

    def receive_message(self, msg):
        func = getattr(self, "on_message_handle", None)
        if func is not None:
            func(msg)
        else:
            self.process_commands(msg)

client = Client()

@client.event
def on_message(msg):
    print("in on_message #1")

@client.event
def on_message(msg):
    print("in on_message #2")

client.receive_message("hello")
# "in on_message #2"

Как вы видите client.event, сохраняйте только один экземпляр on_message.


Вы можете использовать Bot экземпляры

В качестве альтернативы, если вы используете расширение ext.commands для discord.py, есть собственный способ иметь несколько обратных вызовов on_message , Вы делаете это, используя их как listener. Вы можете получить не более одного события on_message и бесконечного количества слушателей on_message.

from discord.ext import commands

bot = commands.Bot('.')

@bot.event
async def on_message(msg):
    print("in on_message #1")
    await bot.process_commands(msg)  # so `Command` instances will still get called


@bot.listen()
async def on_message(msg):
    print("in on_message #2")


@bot.listen()
async def on_message(msg):
    print("in on_message #3")

bot.run("TOKEN")

Когда сообщение будет получено, все on_message #1-3 будут распечатаны.

2
ответ дан abccd 15 August 2018 в 22:48
поделиться

В python функции - это просто объекты.

>>> def foo():
...     print ("hi")

определяет объект с именем foo, вы можете увидеть это с помощью оболочки Python.

>>> foo
<function foo at 0x...>
>>> foo()
hi

Если вы определить новый метод после или переопределить переменную foo, вы потеряете доступ к исходной функции.

>>> foo = "hi"
>>> foo
hi
>>> foo()
Traceback ...:
    file "<stdin>" ...
TypeError: 'str' object is not callable

Как работает декоратор @client.event, он сообщает вашему клиенту, что новые сообщения должны быть связаны по каналам в сообщениях, и хорошо, если метод будет переопределен, это означает, что старый метод потерян.

>>> @bot.event
... async def on_message(m):
...     print(1)
...
>>> bot.on_message(None) # @bot.event makes the bot define it's own method
1
>>> @bot.event
... async def on_message(m):
...     print(2)
...
>>> bot.on_message(None) # bot's own method was redefined.
2
0
ответ дан squaswin 15 August 2018 в 22:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: