Когда оператор возвращает логическое значение, как использовать это значение в операторе if - PullRequest
0 голосов
/ 22 февраля 2020

Я новичок в программировании, и я пытался проверить, существует ли слово в файле. Я поместил слова в словарь (упражнение подсказало мне ввести его как dict в качестве ключа и игнорировать значение), а затем позволил пользователю ввести слово, затем я попытался проверить, является ли оно в словаре.

words_dict = dict()

fhand = open('desktop/codingMaterial/words.txt')
for line in fhand:
    line = line.rstrip()
    t = line.split()
    for word in t:
        words_dict[word] = 0

# check if word exists
v = input('Enter a variable: ')
if v in words_dict == True:
    print('Exist.')
else:
    print('Does not exist.')

Я пытался запустить это, но независимо от того, какое слово я ввел, вывод всегда был 'Не существует.' . Я думаю, что я сделал что-то не так в утверждении if, но я не уверен, как это исправить.

Ответы [ 5 ]

3 голосов
/ 22 февраля 2020

if v in word_dict == True элюируется как if v in word_dict and word_dict==True. Это называется операторным связыванием.

Проверьте этот байт-код, используя модуль dis.

import dis
a={'a':1,'b':2,'c':3}

In [53]: dis.dis('"a" in a == True')
  1           0 LOAD_CONST               0 ('a')
              2 LOAD_NAME                0 (a)
              4 DUP_TOP
              6 ROT_THREE
              8 COMPARE_OP               6 (in)
             10 JUMP_IF_FALSE_OR_POP    18
             12 LOAD_CONST               1 (True)
             14 COMPARE_OP               2 (==)
             16 RETURN_VALUE
        >>   18 ROT_TWO
             20 POP_TOP
             22 RETURN_VALUE
In [54]: dis.dis('"a" in a and a==True')
  1           0 LOAD_CONST               0 ('a')
              2 LOAD_NAME                0 (a)
              4 COMPARE_OP               6 (in)
              6 JUMP_IF_FALSE_OR_POP    14
              8 LOAD_NAME                0 (a)
             10 LOAD_CONST               1 (True)
             12 COMPARE_OP               2 (==)
        >>   14 RETURN_VALUE

Оба вычисляются одинаково. И в вашем случае word_dict==True всегда False, поскольку word_dict это словарь . Таким образом, он никогда не войдет в блок if, и блок else будет выполнен.

if some_bool_expr == True и может быть записан как if some_bool_expr, а if some_bool_expr==False может быть записан как if not some_bool_expr.

Байт-код Ссылка документации документации

LOAD_CONST и LOAD_NAME: pu sh значение в стеке. После строки 2 вершина стека равна a (не 'a')

DUP_TOP: дублирует ссылку на вершине стека и помещает ее в стек. Теперь вершина стека равна a.

ROT_THREE: поднимает второй и третий элементы стека на одну позицию вверх, перемещает сверху вниз на позицию три. Теперь TOS (вершина стека) является третьим элементом (a), а 2-й элемент (a) теперь TOS, 3-й элемент 'a' теперь является 2-м элементом.

COMPARE_OP: Говорит интерпретатору вытолкнуть два верхних элемента стека и выполнить тест на членство (in) между ними, перенеся логический результат обратно в стек. 'a' in a сделано, и результат помещается в стек, т.е. True. Теперь у стека есть TOS как True и дублирующая ссылка от DUP_TOP под ним.

JUMP_IF_FALSE_OR_POP: Если TOS имеет значение false, устанавливает счетчик байт-кода на цель и оставляет TOS в стеке. В противном случае (TOS верно), TOS выскочил. В нашем примере TOS равно True. TOS выскочил. Теперь TOS равно a.

LOAD_CONST True помещено в стек. COMPARE_OP ==. True==a сделано, что False. Теперь TOS равно False.

RETURN_VALUE: Возвращает с TOS вызывающей функции. В нашем примере TOS - это False на данный момент. False возвращается.

POP_TOP: удаляет элемент top-of-stack (TOS).

Единственное различие между обоими выражениями состоит в том, что a вычисляется дважды в 2-й.

Также см. этот ответ: { ссылка }

2 голосов
/ 22 февраля 2020

Проверка того, как оценивается x in y == z, с использованием упаковщиков, которые печатают происходящее:

class C:
    def __init__(self, value):
        self.value = value
    def __eq__(self, other):
        print(self, '==', other)
        return True
    def __contains__(self, value):
        print(value, 'in', self)
        return True
    def __str__(self):
        return str(self.value)

C(1) in C(2) == C(3)

Печатает 1 in 2, затем 2 == 3, , как следует .

Не 1 in 2, за которым следует True == 3.

Не 2 == 3, за которым следует 1 in True.

2 голосов
/ 22 февраля 2020

Удалить == True.
Это должно быть просто.

if v in words_dict:
    print('Exist.')
1 голос
/ 22 февраля 2020

Проверка того, что интерпретатор Python сначала вычисляет подвыражение words_dict == True. И не v in words_dict ( было сделано неверное предположение ). Из других сообщений я вижу, что это утверждение не совсем верно относительно того, что на самом деле делает переводчик. Что довольно интересно. Из других описаний здесь видно, что оператор интерпретации считает оператор in того же уровня приоритета, что и ==. В любом случае вы могли бы сгруппировать первое выражение, чтобы задать порядок вычисления.

>>> words_dict == True
False
>>> 'hand' in words_dict == True
False
>>> 'hand' in words_dict
True
>>> ('hand' in words_dict) == True
True

Если бы это был пример производственного кода, можно было бы реализовать эту логику c как (a in b) == c, если это было намерение выражения. Или, если бы выражение действительно предназначалось для a in b == c, как обсуждалось, то оно могло бы быть реализовано явно как (a in b) and (b == c).

Во многих спецификациях стилей кодирования, которые я видел, есть требование, чтобы разработчики использовали скобки для сгруппируйте их подвыражения в логических выражениях. Независимо от того, считает ли автор, что у него solid гр asp порядка приоритета (без скобок), другие разработчики ценят подход усердия и отсутствия допущений, заключающийся в использовании скобок, а не только в качестве гарантии того, что существует Это не какие-то неправильные предположения, но чтобы показать другим разработчикам предполагаемый порядок приоритета без двусмысленности. Это хороший пример.

Существуют таблицы, показывающие порядок старшинства операторов в сети, которые перечисляют in ниже ==. Тем не менее, это прямо из документов. python .org и точно показывает, что in и == находятся на одном уровне: https://docs.python.org/3/reference/expressions.html#operator -предшественничество

0 голосов
/ 22 февраля 2020

изменить if v in words_dict == True: с if v in words_dict:

Ваша проблема связана с Операторы сравнения цепочек , оба оператора in и == имеют одинаковый приоритет и оцениваются слева направо, эквивалент вашего кода (уже указан @ Ch3steR):

if v in word_dict and word_dict==True
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...