En regardant dans Queue.py dans Python 2.6, j'ai trouvé cette construction que j'ai trouvée un peu étrange:
def full(self):
"""Return True if the queue is full, False otherwise
(not reliable!)."""
self.mutex.acquire()
n = 0 < self.maxsize == self._qsize()
self.mutex.release()
return n
Si la valeur maxsize
est 0, la file d'attente n'est jamais pleine.
Ma question est de savoir comment cela fonctionne pour ce cas? Comment 0 < 0 == 0
est-il considéré comme faux?
>>> 0 < 0 == 0
False
>>> (0) < (0 == 0)
True
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
>>> (0) < (0 == 0)
, ce n'est clairement pas le cas.n = 0 < self.maxsize == self._qsize()
au départ, dans aucune langue. Si vos yeux doivent faire des allers-retours sur la ligne plusieurs fois pour comprendre ce qui se passe, ce n'est pas une ligne bien écrite. Il suffit de le diviser en plusieurs lignes.Réponses:
Je pense que Python a une gestion spéciale des cas pour les séquences d'opérateurs relationnels afin de rendre les comparaisons de plages faciles à exprimer. C'est beaucoup plus agréable de pouvoir dire
0 < x <= 5
que de dire(0 < x) and (x <= 5)
.Celles-ci sont appelées des comparaisons en chaîne . Et c'est un lien vers la documentation pour eux.
Avec les autres cas dont vous parlez, les parenthèses forcent un opérateur relationnel à être appliqué avant l'autre, et donc ce ne sont plus des comparaisons enchaînées. Et depuis
True
etFalse
que les valeurs sont des entiers, vous obtenez les réponses que vous faites à partir des versions entre parenthèses.la source
Car
est
False
. Vous pouvez enchaîner les opérateurs de comparaison et ils sont automatiquement développés dans les comparaisons par paires.EDIT - clarification sur True et False en Python
En Python
True
et neFalse
sont que des instances debool
, qui est une sous-classe deint
. En d'autres termes, c'estTrue
vraiment juste 1.Le but est que vous pouvez utiliser le résultat d'une comparaison booléenne exactement comme un entier. Cela conduit à des choses déroutantes comme
Mais cela ne se produira que si vous mettez entre parenthèses les comparaisons afin qu'elles soient évaluées en premier. Sinon, Python étendra les opérateurs de comparaison.
la source
'success' if result_code == 0 else 'failure'
peut être réécrite comme('error', 'success')[result_code == 0]
, avant cela, je n'avais jamais vu de booléen utilisé pour sélectionner un élément dans une liste / un tuple.Le comportement étrange que vous ressentez provient de la capacité des pythons à enchaîner les conditions. Puisqu'il trouve que 0 n'est pas inférieur à 0, il décide que l'expression entière est évaluée à false. Dès que vous divisez cela en conditions distinctes, vous modifiez la fonctionnalité. Il s'agit essentiellement de tester cela
a < b && b == c
pour votre déclaration originale dea < b == c
.Un autre exemple:
la source
a < b && b == c
est le même quea < b == c
OOCeci est une comparaison en chaîne. Il renvoie vrai si chaque comparaison par paires est à son tour vraie. C'est l'équivalent de
(0 < 0) and (0 == 0)
Cela équivaut à
0 < True
qui prend la valeur True.Cela équivaut à
False == 0
qui prend la valeur True.Équivalent à
0 < True
qui, comme ci-dessus, donne la valeur True.la source
En regardant le démontage (les octets codes) , il est évident pourquoi
0 < 0 == 0
estFalse
.Voici une analyse de cette expression:
Remarquez les lignes 0-8: Ces lignes vérifient si
0 < 0
ce qui renvoie évidemmentFalse
sur la pile python.Remarquez maintenant la ligne 11:
JUMP_IF_FALSE_OR_POP 23
cela signifie que si0 < 0
retourneFalse
effectuez un saut à la ligne 23.Maintenant,
0 < 0
estFalse
, donc le saut est pris, ce qui laisse la pile avec unFalse
qui est la valeur de retour pour l'expression entière0 < 0 == 0
, même si la== 0
partie n'est même pas vérifiée.Donc, pour conclure, la réponse est comme dit dans d'autres réponses à cette question.
0 < 0 == 0
a une signification particulière. Le compilateur évalue cela en deux termes:0 < 0
et0 == 0
. Comme pour toutes les expressions booléennes complexesand
entre elles, si la première échoue, la seconde n'est même pas vérifiée.J'espère que cela éclairera un peu les choses, et j'espère vraiment que la méthode que j'ai utilisée pour analyser ce comportement inattendu encouragera les autres à essayer la même chose à l'avenir.
la source
Comme d'autres l'ont mentionné
x comparison_operator y comparison_operator z
le sucre syntaxique a pour(x comparison_operator y) and (y comparison_operator z)
avantage que y n'est évalué qu'une seule fois.Donc, votre expression
0 < 0 == 0
est vraiment(0 < 0) and (0 == 0)
, qui évalueFalse and True
ce qui est justeFalse
.la source
peut-être que cet extrait de la documentation peut vous aider:
Il s'agissait de comparaisons, mais puisque vous enchaînez des comparaisons, vous devez savoir que:
la source
Le voici, dans toute sa splendeur.
la source
Je pense que Python fait c'est bizarre entre la magie. Identique au
1 < 2 < 3
moyen 2 est compris entre 1 et 3.Dans ce cas, je pense que [middle 0] est supérieur à [left 0] et égal à [right 0]. Le milieu 0 n'est pas supérieur à 0 gauche, il est donc évalué à faux.
la source