Discord.py Bot: рассылает любовь между двумя людьми.

Я создаю Discord Bot, и я сделал команду! Love, которая проверяет уровень любви между двумя людьми или объектами.

Пример:! Love Emma Халат

Результат: Лаврейт между Пеньюаром и Эммой составляет x%.

Вот код:

@bot.command(name="love", aliases=["l"])
async def love(ctx, Personne1, Personne2):
    if ctx.message.channel.id != 763352957579690018:
        printIt = 1
        wordBanList = ['@everyone', '@here', '<@&763489250162507809>','<@&777564025432965121>','<@&822200827347075132>',
                       '<@&763815680306184242>','<@&764422266560839680<','<@&763815728972300338>','<@&763815728972300338>',
                       '<@&763815228323528725>','<@&763815784904261632>','<@&764422166116171806>','<@&764422057353936897>',
                       '<@&804807279043674143>','<@&828664814678179861>','<@&823562218095640646>','<@&823638574809219163>']
        LoveRate = str(random.randrange(0, 100))
        for y in range(len(wordBanList)):
            if(Personne1 == wordBanList[y] or Personne2 == wordBanList[y]):
                printIt = 0

        if(printIt == 0):
            await ctx.send("Tu t'es pris pour qui ?")
            if debug == True:
                print("[DEBUG] !love : Someone tried to use a banned word !")
        else:
            await ctx.send("L'amour entre **"+Personne1+"** et **"+Personne2+"** est de **"+LoveRate+"%** <:flushed:830502924479758356>")
            if debug == True:
                print("[DEBUG] !love : The love rate ("+LoveRate+"%) between "+Personne1+" and "+Personne2+" has been printed in channel ID "+str(ctx.channel.id))
    else:
        botChannel = discord.utils.get(ctx.guild.channels, id=768194273970880533)
        messageBot = await ctx.send("Va faire cette commande dans "+botChannel.mention+" ou je te soulève <:rage:831149184895811614>")
        await asyncio.sleep(5)
        await ctx.message.delete()
        await messageBot.delete()

Я почти уверен, что этот код можно оптимизировать, но я не знаю, как, может кто-нибудь мне помочь :)?

2 ответа
2

Никогда не перебирать индексы в Python

В Python этот шаблон обычно не рекомендуется:

for y in range(len(wordBanList)):
    if(Personne1 == wordBanList[y] or Personne2 == wordBanList[y]):
        printIt = 0

Вам почти никогда не нужно перебирать элементы и обращаться к ним по их индексам. Вместо этого вы должны напрямую перебирать элементы итерации:

for word in wordBanList:
    if Personne1 == word or Personne2 == word:
        printIt = 0

Также обратите внимание, что скобки вокруг or утверждение.

Если вам нужен индекс, вы можете использовать встроенный enumerate:

for index, word in enumerate(wordBanList):
    ...

Тесты на членство

Как указал Харша, setоптимизированы для тестирования членства, поэтому используйте их, когда это возможно. Это также может сделать ваше задание printIt способ более краткий:

wordBanList = {'@everyone', '@here', '<@&763489250162507809>', ...}
printIt = 0 if (Personne1 in wordBanList or Personne2 in wordBanList) else 1

Скобки здесь также не требуются, но могут улучшить читаемость.


Соглашение об именовании

PEP 8:

Имена функций должны быть в нижнем регистре, а слова должны быть разделены подчеркиванием по мере необходимости для повышения удобочитаемости.

Имена переменных следуют тому же соглашению, что и имена функций.

Имена переменных и функций должны следовать за snake_case.


debug == True

Как правило, вы всегда должны использовать is со встроенными константами: True, False а также None. Также может быть достаточно проверить debug за правдивость (if debug:). Однако это зависит от варианта использования, поскольку выражения не эквивалентны. Второй не сработает для всех ложных значений, а не только False (например, пустая строка, пустой список). Если вам интересно, вы можете узнать больше о Истинные и ложные значения в Python.


Форматирование строки

LoveRate = str(random.randrange(0, 100))

LoveRate (или лучше love_rate) не должно быть типа str, так как вам нужен только его str— подготовка к печати. Вы можете позволить Python обрабатывать форматирование за вас, используя ф-струны. Таким образом, вам никогда не придется думать о кастинге на str.

print("[DEBUG] !love : The love rate ("+LoveRate+"%) between "+Personne1+" and "+Personne2+" has been printed in channel ID "+str(ctx.channel.id))

становится

print(f"[DEBUG] !love : The love rate ({LoveRate}%) between {Personne1} and {Personne2} has been printed in channel ID {ctx.channel.id}")

Еще несколько мелких моментов:

  1. Вместо того, чтобы оборачивать основной код внутри if-else-блок мы можем использовать ctx.message.channel.id == 763352957579690018 как условие выхода.
  2. print_it относится к типу int, но в основном действует как переменная типа bool. Мы также можем полностью исключить эту переменную, поскольку используем ее только один раз.
  3. В идеале длина строки не должна превышать 80 символов. Вы можете использовать скобки для удобного объединения строк в несколько строк, как описано в этом Совет Reddit. В моей среде IDE установлено жесткое обертывание только для 100 символов, так что это максимальная длина строк ниже.
@bot.command(name="love", aliases=["l"])
async def love(ctx, personne1, personne2):
    if ctx.message.channel.id == 763352957579690018:
        bot_channel = discord.utils.get(ctx.guild.channels, id=768194273970880533)
        message_bot = await ctx.send(f"Va faire cette commande dans {bot_channel.mention} "
                                     f"ou je te soulève <:rage:831149184895811614>")
        await asyncio.sleep(5)
        await ctx.message.delete()
        await message_bot.delete()
        return

    word_ban_list = {'@everyone', '@here', '<@&763489250162507809>', '<@&777564025432965121>',
                     '<@&822200827347075132>', '<@&763815680306184242>', '<@&764422266560839680<',
                     '<@&763815728972300338>', '<@&763815728972300338>', '<@&763815228323528725>',
                     '<@&763815784904261632>', '<@&764422166116171806>', '<@&764422057353936897>',
                     '<@&804807279043674143>', '<@&828664814678179861>', '<@&823562218095640646>',
                     '<@&823638574809219163>'}

    love_rate = str(random.randrange(0, 100))

    if personne1 in word_ban_list or personne2 in word_ban_list:
        await ctx.send("Tu t'es pris pour qui ?")
        if debug:
            print("[DEBUG] !love : Someone tried to use a banned word !")
    else:
        await ctx.send(f"L'amour entre **{personne1}** et **{personne2}** est de **{love_rate}%** "
                       f"<:flushed:830502924479758356>")
        if debug:
            print(f"[DEBUG] !love : The love rate ({love_rate}%) between {personne1} and"
                  f"{personne2} has been printed in channel ID {ctx.channel.id}")

  • 2

    Ух ты! Спасибо за ответ, мне действительно помогло. Я очень рад получить такие ответы на свой первый вопрос, сообщество Stack Exchange очень дружелюбно и полезно! 🙂 Если вы хотите проверить наш проект на Github, вы можете нажать здесь

    — Я в халате


  • 2

    @JSuisEnPeignoir Я бы также рекомендовал использовать logging модуль над теми print заявления.

    — hjpotter92

  • @ hjpotter92 Хорошо, я посмотрю, спасибо тебе за помощь! 🙂

    — Я в халате

for y in range(len(wordBanList)):
            if(Personne1 == wordBanList[y] or Personne2 == wordBanList[y]):
                printIt = 0

Этот код проверяет, находится ли Personne1 или Personne2 в wordBanList и имеет ли время выполнения O (len (wordBanList)). Вы можете изменить тип данных вашего wordBanList на set () и иметь время выполнения O (1). Таким образом, ваш код может быть преобразован в:

if Personne1 in wordBanList or Personne2 in wordBanList:
    printIt = 0

PS: Если у вас небольшой wordBanList (например, 10 000 000), разница значительна. https://towardsdatascience.com/faster-lookups-in-python-1d7503e9cd38

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *