2010-04-05 9 views
4

Pour une raison quelconque cette fonction me confondre:Comment "et" et "ou" fonctionnent lorsqu'ils sont combinés en une seule instruction?

def protocol(port): 
    return port == "443" and "https://" or "http://" 

quelqu'un peut-il expliquer l'ordre de ce qui se passe dans les coulisses pour faire ce travail comme il le fait.

je l'ai compris comme cela jusqu'à ce que je l'ai essayé:

Soit A)

def protocol(port): 
    if port == "443": 
     if bool("https://"): 
      return True 
    elif bool("http://"): 
     return True 
    return False 

Ou B)

def protocol(port): 
    if port == "443": 
     return True + "https://" 
    else: 
     return True + "http://" 

Est-ce une sorte de cas particulier en Python, ou suis J'ai complètement mal compris comment fonctionnent les énoncés?

+0

@Responders, voir mon jour 1 minute plus tard. Pardon. – orokusaki

+1

Rappelez-vous simplement que les instructions 'et' et 'or' renvoient la dernière expression à évaluer. :) –

Répondre

21

C'est un vieux idiome; insérer entre parenthèses pour montrer la priorité,

(port == "443" and "https://") or "http://" 

x and y retours y si x est truish, x si x est falsish; a or b, vice versa, renvoie a s'il est vrai, sinon b. Donc, si port == "443" est vrai, ceci retourne le RHS du and, c'est-à-dire "https://". Sinon, le and est faux, donc le or entre en jeu et retourne `" "http: //", son RHS.

En Python moderne, une meilleure façon de traduire cet idiome ne ancien ish est:

"https://" if port == "443" else "http://" 
+0

@Alex +1 Merci pour l'explication détaillée. Ils ont apparemment fait en sorte que je ne peux pas accepter une réponse pendant 10 minutes :(mais bonne réponse – orokusaki

+0

@orokusaki, merci, et je suis sûr que vous serez en mesure de l'accepter plus tard ;-). –

+0

+1 pour mentionner l'opérateur ternaire de python, beaucoup plus facile à lire/comprendre imho – tosh

8

and renvoie l'opérande de droite si la gauche est vraie. or renvoie l'opérande de droite si la gauche est fausse. Sinon, ils retournent tous les deux l'opérande gauche. Ils sont dits coalesce.

+0

Ah, merci Ignacio. Je ne sais pas comment je suis arrivé si loin en Python sans comprendre cela. C'est la première fois que je vois ça utilisé exactement comme ça. +1 – orokusaki

+2

http://docs.python.org/tutorial/datastructures.html#more-on-conditions – wRAR

2

Ceci est une bidouille horrible qui n'est pas recommandé. Cela fonctionne en raison du comportement de court-circuit de and et or et qu'ils retournent l'un de leurs arguments plutôt qu'une valeur booléenne. L'utilisation de cette technique risque d'introduire des bogues difficiles à trouver, ne l'utilisez donc pas dans un nouveau code.

Voici un exemple de la façon dont l'idiome and/or peut donner un résultat inattendu:

>>> foo = 'foobar' 
>>> bar = 'foobar' 
>>> x = 0 
>>> y = 1 
>>> (foo == bar) and x or y # Will this return the value of x if (foo == bar)? 
1 

Préférez plutôt la notation plus récente:

return "https://" if port == "443" else "http://" 
+0

@Mark C'est la version que je connais, et je n'ai jamais vu la version dans mon post jusqu'à aujourd'hui. +1 – orokusaki

1

Vous pouvez lire sur le « et/ou astuce "de Python dans cet article The Peculiar Nature of And and Or in Python. C'est un peu comme le IIF() en VBA ou VB, ou ?: dans les langages de style C.

+0

@Abel Merci. Je viens de le lire, article intéressant. J'ai beaucoup utilisé la syntaxe 'return a ou b', mais pour une raison quelconque, cet extrait ne jive pas. – orokusaki

0

Cette construction fonctionne parce qu'il se déroule "au code suivant:

a et b ->

if a: 
    return b 
else: 
    return a 

a ou b ->

if a: 
    return a 
else: 
    return b 
5

C and X or Y est le tentative précoce de longue durée par les utilisateurs Python de proxy pour C ? X : Y

Pour la plupart, cela fonctionne, sauf si X est False - cela a conduit à de nombreux bugs dans le code Python, donc dans le Python FAQ, vous trouverez la solution la plus correcte étant (C and [X] or [Y])[0] car une liste avec un seul élément, indépendamment de sa valeur booléenne évaluée, est toujours True! Par exemple: [None] est True mais None ne l'est pas. L'exemple de l'OP ci-dessus fonctionne parce que la chaîne représentant X n'est pas vide.

Cependant, tout cela a changé dans Python 2.5, lorsque l'opérateur ternaire ou conditionnel a été ajouté au langage, vous permettant d'utiliser le nettoyeur X if C else Y comme indiqué dans d'autres publications ici. Si vous voyez du code en utilisant l'ancien format, c'est parce que l'utilisateur a été un programmeur Python depuis longtemps qui n'a pas encore adopté la nouvelle syntaxe, il coupe-n-colle un autre ancien code, ou son employeur utilise encore 2.4.x (ou les versions précédentes), etc.

0

Avec toutes les bonnes réponses, je trouve ces déclarations me souviens aider mieux et en forme comment mon cerveau (et je l'espère pour pour un peu plus là-bas):

  • "Et" renvoie le premier élément Faux (par exemple, Aucun, "", [],(), {}, 0) ou le dernier élément si aucun (par exemple aucun Faux trouvé)

  • "ou" renvoie le premier élément True ou le dernier élément (par ex. pas vrai trouvé) **

En résumé:

  • ils reviennent tout le premier élément qui décide de l'issue de la déclaration. (Dans le pire des cas, le dernier élément de la séquence)

Notez cette règle s'applique également à une chaîne tout « et » ou tout « ou » déclaration