109 votes

L'associativité de "en" en Python?

Je suis en train de faire un Python de l'analyseur, et c'est vraiment déroutant moi:

>>>  1 in  []  in 'a'
False

>>> (1 in  []) in 'a'
TypeError: 'in <string>' requires string as left operand, not bool

>>>  1 in ([] in 'a')
TypeError: 'in <string>' requires string as left operand, not list

Comment fonctionne exactement "dans" le travail en Python, en ce qui concerne l'associativité, etc.?

Pourquoi ne pas faire de deux de ces expressions se comportent de la même façon?

124voto

Ashwini Chaudhary Points 94431

1 in [] in 'a' est évaluée comme (1 in []) and ([] in 'a').

Depuis la première condition (1 in []) False, l'ensemble de la condition est évaluée comme False; ([] in 'a') n'est jamais réellement évalué, aucune erreur n'est générée.

Voici la déclaration de définitions:

In [121]: def func():
   .....:     return 1 in [] in 'a'
   .....: 

In [122]: dis.dis(func)
  2           0 LOAD_CONST               1 (1)
              3 BUILD_LIST               0
              6 DUP_TOP             
              7 ROT_THREE           
              8 COMPARE_OP               6 (in)
             11 JUMP_IF_FALSE            8 (to 22)  #if first comparison is wrong 
                                                    #then jump to 22, 
             14 POP_TOP             
             15 LOAD_CONST               2 ('a')
             18 COMPARE_OP               6 (in)     #this is never executed, so no Error
             21 RETURN_VALUE         
        >>   22 ROT_TWO             
             23 POP_TOP             
             24 RETURN_VALUE        

In [150]: def func1():
   .....:     return (1 in  []) in 'a'
   .....: 

In [151]: dis.dis(func1)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               3 (())
              6 COMPARE_OP               6 (in)   # perform 1 in []
              9 LOAD_CONST               2 ('a')  # now load 'a'
             12 COMPARE_OP               6 (in)   # compare result of (1 in []) with 'a'
                                                  # throws Error coz (False in 'a') is
                                                  # TypeError
             15 RETURN_VALUE   



In [153]: def func2():
   .....:     return 1 in ([] in 'a')
   .....: 

In [154]: dis.dis(func2)
  2           0 LOAD_CONST               1 (1)
              3 BUILD_LIST               0
              6 LOAD_CONST               2 ('a') 
              9 COMPARE_OP               6 (in)  # perform ([] in 'a'), which is 
                                                 # Incorrect, so it throws TypeError
             12 COMPARE_OP               6 (in)  # if no Error then 
                                                 # compare 1 with the result of ([] in 'a')
             15 RETURN_VALUE        

24voto

Alexander Chen Points 632

Python n'choses spéciales avec enchaîné les comparaisons.

Les éléments suivants sont évalués de façon différente:

x > y > z   # in this case, if x > y evaluates to true, then
            # the value of y is being used to compare, again,
            # to z

(x > y) > z # the parenth form, on the other hand, will first
            # evaluate x > y. And, compare the evaluated result
            # with z, which can be "True > z" or "False > z"

Dans les deux cas, si la première comparaison, est - False, le reste de l'énoncé ne sera pas examiné.

Pour votre cas particulier,

1 in [] in 'a'   # this is false because 1 is not in []

(1 in []) in a   # this gives an error because we are
                 # essentially doing this: False in 'a'

1 in ([] in 'a') # this fails because you cannot do
                 # [] in 'a'

Aussi, afin de démontrer la première règle ci-dessus, ce sont des états qui sont évaluées à True.

1 in [1,2] in [4,[1,2]] # But "1 in [4,[1,2]]" is False

2 < 4 > 1               # and note "2 < 1" is also not true

La priorité de python opérateurs: http://docs.python.org/reference/expressions.html#summary

11voto

phant0m Points 8545

À partir de la documentation:

Des comparaisons peuvent être enchaînés de manière arbitraire, par exemple, x < y <= z est équivalent à x < y et y <= z, sauf que y est évaluée qu'une seule fois (mais dans les deux cas, z n'est pas évalué si x < y est fausse).

Ce qui veut dire, qu'il n'y pas d'associativité en x in y in z!

Les suivantes sont équivalentes:

1 in  []  in 'a'
# <=>
middle = []
#            False          not evaluated
result = (1 in middle) and (middle in 'a')


(1 in  []) in 'a'
# <=>
lhs = (1 in []) # False
result = lhs in 'a' # False in 'a' - TypeError


1 in  ([] in 'a')
# <=>
rhs = ([] in 'a') # TypeError
result = 1 in rhs

3voto

Peter Points 14647

La réponse courte, depuis le long on est déjà plusieurs fois ici et dans d'excellentes manières, c'est que l'expression booléenne est court-circuitée, c'est a cessé d'évaluation lors d'un changement de vrai dans le faux, ou vice versa ne peut pas arriver par une autre évaluation.

(voir http://en.wikipedia.org/wiki/Short-circuit_evaluation)

Il peut être un peu court (sans mauvais jeu de mots) comme une réponse, mais comme mentionné, tous les autres explication est deja fait très bien ici, mais je pensais que le terme mérite d'être mentionné.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X