Je suis un nouvel apprenant en programmation et j'essayais de vérifier si un mot existe dans un fichier. J'ai mis les mots dans un dictionnaire (l'exercice m'a dit de le mettre dans un dict comme clé et d'ignorer la valeur), puis j'ai laissé l'utilisateur saisir un mot, puis j'ai essayé de vérifier s'il est dans le dictionnaire.

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.')

J'ai essayé d'exécuter ceci, mais quel que soit le mot que j'entre, la sortie était toujours 'N'existe pas.' . Je pense que j'ai fait quelque chose de mal dans la déclaration if, mais je ne sais pas comment y remédier.

-1
May Ding 22 févr. 2020 à 19:48

5 réponses

Meilleure réponse

if v in word_dict == True est remplacé par if v in word_dict and word_dict==True. C'est ce qu'on appelle le chaînage des opérateurs.

Vérifiez ce code d'octet à l'aide du module 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

Les deux sont évalués de la même manière. Et dans votre cas, word_dict==True est toujours False car word_dict est un dictionnaire . Ainsi, il n'entrerait jamais dans le bloc if et le bloc else est exécuté.

if some_bool_expr == True et peut être écrit comme if some_bool_expr et if some_bool_expr==False peut être écrit comme if not some_bool_expr.

Lien vers la documentation des instructions de code octet

LOAD_CONST et LOAD_NAME: poussez la valeur sur la pile. Après la ligne 2, en haut de la pile est a (pas 'a')

DUP_TOP: Duplique la référence en haut de la pile et pousse sur la pile. Maintenant, en haut de la pile est a.

ROT_THREE: soulève le deuxième et le troisième élément de la pile d'une position vers le haut et descend de haut en troisième position. Maintenant TOS (en haut de la pile) est le troisième élément (a) et le deuxième élément (a) est maintenant TOS, le troisième élément 'a' est maintenant 2e élément.

COMPARE_OP: indique à l'interpréteur de faire apparaître les deux éléments de pile supérieurs et d'effectuer un test d'appartenance (in) entre eux, en repoussant le résultat booléen sur la pile. 'a' in a est terminé et le résultat est poussé sur la pile, c'est-à-dire True. Maintenant, la pile a TOS comme True et la référence en double de DUP_TOP en dessous.

JUMP_IF_FALSE_OR_POP: Si TOS est faux, définit le compteur de bytecode sur target et laisse TOS sur la pile. Sinon (TOS est vrai), TOS est sauté. Dans notre exemple, TOS est donc True. TOS est sauté. Maintenant, TOS est a.

LOAD_CONST True est poussé sur la pile. COMPARE_OP ==. True==a est terminé qui False. Maintenant, TOS est False.

RETURN_VALUE: Retourne avec TOS à l'appelant de la fonction. Dans notre exemple, TOS est False à ce stade. False est retourné.

POP_TOP: supprime l'élément de haut de pile (TOS).

La seule différence entre les deux expressions est que a est évalué deux fois dans la seconde.

Reportez-vous également à cette réponse: https://stackoverflow.com/a/3299724/12416453

3
Ch3steR 23 févr. 2020 à 04:00

Un test de la façon dont x in y == z est évalué, en utilisant des wrappers qui affichent ce qui se passe:

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)

Imprime 1 in 2 suivi de 2 == 3, comme il se doit.

Pas 1 in 2 suivi de True == 3.

Pas 2 == 3 suivi de 1 in True.

2
Heap Overflow 22 févr. 2020 à 20:50

Vérifier que l'interpréteur Python évalue d'abord la sous-expression words_dict == True. Et pas v in words_dict ( une hypothèse erronée a été émise ). Je vois dans d'autres articles que cette déclaration n'est pas exacte sur ce que fait réellement l'interprète. Ce qui est assez intéressant. D'après d'autres descriptions ici, il semble que l'interp considère l'opérateur in comme étant au même niveau de priorité que ==. Dans les deux cas, vous pouvez regrouper la première expression pour forcer l'ordre d'évaluation.

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

S'il s'agissait d'un exemple de code de production, on pourrait implémenter cette logique comme (a in b) == c si telle était l'intention de l'expression. Ou si l'expression était vraiment destinée à être a in b == c comme discuté, alors elle pourrait être implémentée explicitement comme (a in b) and (b == c).

Dans de nombreuses spécifications de style de codage que j'ai vues, les développeurs doivent utiliser des parenthèses pour regrouper leurs sous-expressions dans des expressions booléennes. Que l'auteur pense ou non avoir une solide compréhension de l'ordre de priorité (sans parenthèses), les autres développeurs apprécient l'approche diligente et sans hypothèses de l'utilisation des parenthèses, non seulement comme garantie pour s'assurer qu'il n'y a pas d'hypothèses incorrectes , mais pour montrer aux autres développeurs l'ordre de priorité prévu sans ambiguïté. C'est un bon exemple.

Il existe des tableaux indiquant l'ordre de priorité des opérateurs en ligne qui répertorient in ci-dessous ==. Cependant, celui-ci provient directement de docs.python.org et montre avec précision que in et == sont au même niveau: https://docs.python.org/3/reference/expressions.html#operator-precedence

1
Todd 22 févr. 2020 à 22:24

Supprimez le == True.
Ça devrait être juste.

if v in words_dict:
    print('Exist.')
2
Akhil Nambiar 22 févr. 2020 à 16:51

Changer if v in words_dict == True: par if v in words_dict:

Votre problème est lié aux chaînage des opérateurs de comparaison, les deux opérateurs {{X0} } et == ont la même priorité et sont évalués de gauche à droite, un équivalent de votre code est (déjà indiqué par @ Ch3steR):

if v in word_dict and word_dict==True
0
kederrac 22 févr. 2020 à 18:05