2010-07-05 4 views
15

En python si vous écrivez quelque chose commePython expression booléenne et ou

foo==bar and spam or eggs 

python semble revenir spam si la déclaration booléenne est vraie et les œufs autrement. Quelqu'un pourrait-il expliquer ce comportement? Pourquoi l'expression n'est-elle pas évaluée comme un long booléen? Éditer: Spécifiquement, j'essaye de comprendre le mécanisme pourquoi le «spam» ou les «oeufs» sont renvoyés en raison de l'expression. Essayez d'utiliser des parenthèses pour rendre l'expression non ambiguë.

Répondre

14

Les opérateurs and et or sont court-circuit qui signifie que si le résultat de l'expression peut être déduite de la seule évaluation de la première l'opérande, le second n'est pas évalué. Par exemple si vous avez l'expression a or b et a évalue à vrai alors peu importe ce que b est, le résultat de l'expression est vrai, donc b n'est pas évalué. Ils travaillent en fait comme suit:

  • a and b: Si un est Falsey, b n'est pas évaluée et est retourné, sinon b est retourné.
  • a or b: Si a est vrai, b n'est pas évalué et a est retourné, sinon b est retourné. Falsey et truthy se réfèrent à des valeurs qui sont fausses ou vraies dans un contexte booléen.

Cependant cela et/ou idiome a été utile à l'époque où il n'y avait pas de meilleure alternative, mais maintenant il y a une meilleure façon:

spam if foo==bar else eggs 

Le problème avec le et/ou idiome (en dehors de celui-ci être déroutant pour les débutants) est qu'il donne le mauvais résultat si la condition est vraie, mais le spam évalue à une valeur Falsey (par exemple la chaîne vide). Pour cette raison, vous devriez l'éviter.

+1

'spam si foo == bar ou eggs' affiche une erreur de syntaxe dans python 2.6.5, mais 'spam si foo == bar else eggs' fonctionne comme prévu. – Zxaos

+0

@Zxaos: Désolé à ce sujet. Il aurait dû être 'else' pas' ou'. Fixé maintenant –

+1

Dans "le mauvais résultat ... si foo évalue à une valeur de falsey" vouliez-vous dire "le spam évalue à une valeur falsey"? – unutbu

2

La façon dont il est, vous obtenez:

(foo == bar and spam) or eggs 
+0

+1 pour me battre à ce – derekerdmann

+0

Je comprends qu'il est d'être court-circuité, mais je ne suis pas sûr pourquoi le spam ou les œufs sont retournés à la suite de l'évaluation. – Zxaos

3

La raison en est que Python évalue l'expression booléenne en utilisant les valeurs réelles des variables impliquées, au lieu de les limiter à True et False valeurs. Les valeurs suivantes sont considérées comme fausses:

  • None
  • False
  • 0 de tout type numérique
  • de séquence vide ou un ensemble ('', (), [], {})
  • définis par l'utilisateur types avec __nonzero__() ou __len__() méthode qui renvoie 0 ou False

Consultez la section Truth Value Testing de la documentation Python pour plus d'informations. En particulier:

opérations et fonctions intégrées qui ont un résultat booléen retourne toujours 0 ou False pour faux et 1 ou True pour vrai, sauf indication contraire. (Exception. Important: les opérations booléennes or et and reviennent toujours l'un de leurs opérandes)

+0

Ok, donc supposons que foo et bar sont égaux. L'interpréteur doit alors évaluer True et le spam, ce qui devrait être True, alors pourquoi le spam est-il retourné? Edit: Ah, d'accord. Je vois des docs. – Zxaos

+0

@Zxaos: J'ai mis à jour ma réponse avec la citation de la documentation qui explique la raison. –

5

Voici comment fonctionnent les opérateurs booléens Python.

De the documentation (le dernier paragraphe explique pourquoi il est une bonne idée que les opérateurs travaillent comme ils le font):

Dans le cadre des opérations booléennes, et aussi quand les expressions sont utilisées par contrôle déclarations de flux, les valeurs suivantes sont interprétées comme faux: False, None, zéro numérique de tous les types et les chaînes vides et conteneurs (y compris les chaînes, tuples, listes , des dictionnaires, des ensembles et frozensets). Toutes les autres valeurs sont interprétées comme vraies. (Voir la __nonzero__() méthode spéciale pour un moyen de changer cela.)

L'opérateur not cède True si son argument est faux, False autrement. L'expression x and y évalue d'abord ; si x est faux, sa valeur est renvoyée; sinon, y est évalué et la valeur résultante est renvoyée. L'expression x or y évalue d'abord x; si x est vrai, sa valeur est renvoyée; sinon, y est évalué et la valeur résultante est renvoyée.

(Notez que ni and ni or restreindre la valeur et le type qu'ils reviennent à False et True, mais plutôt revenir l' dernier argument évalué. C'est parfois utile, par exemple, si s est une chaîne qui devrait être remplacé par une valeur par défaut si elle est vide, l'expression s or 'foo' donne la valeur souhaitée. Parce que not doit inventer une valeur de toute façon, il ne la peine de retourner une valeur du mêmeTypecomme argument, donc par exemple, not 'foo' cède False, pas ''.)

+0

+1 pour le lien aux docs. –