Как работают логические операторы в операторе if с Python?

if "link?" or "Link?" in comment.body and comment.id not in comments_replied_to and comment.author != r.user.me():
        print ("Link String found " + comment.id)
        print(comment.body)
        #comment.reply("Here you go!")
        print ("Replied to comment ")
        #time.sleep(600)

Когда я запускаю код, он пропускает первую "ссылку", или, скорее, он запускает код внутри оператора if независимо от того, "ссылка" или нет? находится в comment.body. Я пытаюсь запустить код как:

if (a or b) and c and d

Где он ищет строку "ссылка?" или строка "Ссылка?" в теле комментария. Если один из них найден, он будет запускать код в цикле for. В настоящее время работает, если у меня есть:

if "link?" in comment.body and comment.id not in comments_replied_to and comment.author != r.user.me():

Так что я знаю, что это "или" оператор, который не так. Просто я привык к программированию на Java, где операторы можно заключать в квадратные скобки.

1 ответ

Следующие:

if "link?" or "Link?" in comment.body and comment.id not in comments_replied_to and comment.author != r.user.me()

Становится что-то вроде этого:

bool("link") OR ("Link?" in comment.body) AND (comment.id not in...), etc.

Это первое значение "ссылка" всегда будет True потому что только пустые строки False-y.


Давайте разберемся!

Этот вопрос, кажется, часто возникает, и я думаю, что это хорошая возможность проверить дизассемблер Python!

In [1]: import dis
In [3]: def func(comment):
   ...:     if "link?" or "Link?" in comment.body and comment.id not in comments_replied_to and comment.autho
   ...: r != r.user.me():
   ...:         print ("Link String found " + comment.id)
   ...:         print(comment.body)
   ...:         #comment.reply("Here you go!")
   ...:         print ("Replied to comment ")
   ...:     

In [4]: dis.dis(func)
  2           0 LOAD_CONST               1 ('link?')
              3 POP_JUMP_IF_TRUE        60
              6 LOAD_CONST               2 ('Link?')
              9 LOAD_FAST                0 (comment)
             12 LOAD_ATTR                0 (body)
             15 COMPARE_OP               6 (in)
             18 POP_JUMP_IF_FALSE      100
             21 LOAD_FAST                0 (comment)
             24 LOAD_ATTR                1 (id)
             27 LOAD_GLOBAL              2 (comments_replied_to)
             30 COMPARE_OP               7 (not in)
             33 POP_JUMP_IF_FALSE      100
             36 LOAD_FAST                0 (comment)
             39 LOAD_ATTR                3 (author)
             42 LOAD_GLOBAL              4 (r)
             45 LOAD_ATTR                5 (user)
             48 LOAD_ATTR                6 (me)
             51 CALL_FUNCTION            0 (0 positional, 0 keyword pair)
             54 COMPARE_OP               3 (!=)
             57 POP_JUMP_IF_FALSE      100

Посмотрите, как написано "LOAD CONST", а затем после этого "POP JUMP IF TRUE". Это означает, что больше ничего не оценивается в этой строке, потому что CONST всегда будет правдой.

Для сравнения, ниже, вы получите это:

              6 LOAD_CONST               2 ('Link?')
              9 LOAD_FAST                0 (comment)
             12 LOAD_ATTR                0 (body)
             15 COMPARE_OP               6 (in)
             18 POP_JUMP_IF_FALSE      100

Вот как выглядит реальное сравнение: оно использует бинарный оператор in сравнить CONST с загруженным ATTR, Вопрос для тех, кто обращает внимание: почему этот POP_JUMP_IF_FALSE и не POP_JUMP_IF_TRUE как первый?

Вы можете попробовать это дома! Загрузите dis и начать разборку!

Другие вопросы по тегам