Я создаю 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 ответа
Никогда не перебирать индексы в 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
Скобки здесь также не требуются, но могут улучшить читаемость.
Соглашение об именовании
Имена функций должны быть в нижнем регистре, а слова должны быть разделены подчеркиванием по мере необходимости для повышения удобочитаемости.
Имена переменных следуют тому же соглашению, что и имена функций.
Имена переменных и функций должны следовать за 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}")
Еще несколько мелких моментов:
- Вместо того, чтобы оборачивать основной код внутри
if-else-блок мы можем использоватьctx.message.channel.id == 763352957579690018как условие выхода. print_itотносится к типуint, но в основном действует как переменная типаbool. Мы также можем полностью исключить эту переменную, поскольку используем ее только один раз.- В идеале длина строки не должна превышать 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}")
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

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