Quelle est la signification de «(1,) == 1» en Python?

119

Je teste la structure du tuple et j'ai trouvé que c'était étrange lorsque j'utilise l' ==opérateur comme:

>>>  (1,) == 1,
Out: (False,)

Lorsque j'attribue ces deux expressions à une variable, le résultat est vrai:

>>> a = (1,)
>>> b = 1,
>>> a==b
Out: True

Cette question est différente de la règle de syntaxe de virgule de fin de tuple Python à mon avis. Je demande au groupe d'expressions entre ==opérateur.

Pythoner
la source
16
En regardant une question précédente du PO il y a à peine 2 heures, il semble merveilleux (ou étrange) que le simple fait de formuler une question différemment puisse conduire à des résultats différents (et à une acceptation au sein de la communauté).
AKS
24
@AKS Ce sont des questions différentes
kmaork
7
@AKS Bien que les questions soient légèrement différentes ici, je suis entièrement d'accord avec votre point de vue. Effet de troupeau aka HNQ.
Insane
5
@PythonNewHand En effet, c'est tout à fait acceptable. C'est pourquoi j'ai ajouté que la formulation d'une question différemment .
AKS
3
@CiroSantilli 巴拿馬 文件 六四 事件 法轮功 comment pensez-vous? J'ai parcouru ces réponses et je n'ai rien vu qui semblait couvrir cette situation particulière.
Dan Getz

Réponses:

88

D'autres réponses vous ont déjà montré que le comportement est dû à la priorité des opérateurs, comme documenté ici .

Je vais vous montrer comment trouver la réponse vous-même la prochaine fois que vous aurez une question similaire à celle-ci. Vous pouvez déconstruire la façon dont l'expression analyse à l'aide du astmodule:

>>> import ast
>>> source_code = '(1,) == 1,'
>>> print(ast.dump(ast.parse(source_code), annotate_fields=False))
Module([Expr(Tuple([Compare(Tuple([Num(1)], Load()), [Eq()], [Num(1)])], Load()))])

À partir de là, nous pouvons voir que le code est analysé comme l'a expliqué Tim Peters :

Module([Expr(
    Tuple([
        Compare(
            Tuple([Num(1)], Load()), 
            [Eq()], 
            [Num(1)]
        )
    ], Load())
)])
wim
la source
1
Un autre outil utile est dis- Dans ce cas, vous en verrez deux LOAD_CONSTavec des valeurs différentes ( (1,)et 1) et un BUILD_TUPLEcode opp.
mgilson
153

C'est juste la priorité des opérateurs. Votre première

(1,) == 1,

groupes comme ça:

((1,) == 1),

donc construit un tuple avec un seul élément à partir du résultat de la comparaison du tuple 1,à un élément à l'entier 1pour l'égalité Ils ne sont pas égaux, vous obtenez donc le tuple 1 False,pour un résultat.

Tim Peters
la source
61
Pas vraiment, mais les 1-tuples ont une syntaxe étrange. En général, vous seriez beaucoup plus surpris si, par exemple, 1+2, 2==3, 4*7ne groupait pas en tant que (1+2), (2==3), (4*7). En pratique, les 1-tuples ne sont presque jamais utilisés (enfin, en dehors des questions StackOverflow ;-)).
Tim Peters
6
Peut-être que «inattendu» aurait été un meilleur mot à utiliser que «étrange». J'ai un peu l'impression de regarder l' un de ces dessins qui peut être deux choses, selon votre perspective et votre concentration . L'opérateur d'égalité est si grand par rapport aux virgules, il est facile de se concentrer dessus et de supposer que le résultat sera True/ False. Maintenant que je comprends ce qui se passe, c'est parfaitement évident et raisonnable.
skrrgwasme
31
Et maintenant vous savez ce que signifie le "Zen of Python" en disant que la seule façon évidente de le faire "peut ne pas être évidente au début à moins que vous ne soyez néerlandais" ;-)
Tim Peters
7
C'est un peu déroutant quand vous lisez le document et voyez que ce qui fait un tuple est la virgule, pas les parenthèses! Donc, dans cette déclaration, la virgule dans la main droite n'est pas considérée comme faisant partie du test mais elle est considérée comme un séparateur! Comportement inattendu!
Ikra_5
3
Le conseil courant sur les expressions est "en cas de doute, utilisez des parenthèses". Ensuite, il est bon de mettre des parenthèses autour de tous les tuples uniques, même s'ils ne font pas partie de la syntaxe des tuples.
nigel222
12

Quand tu fais

>>> (1,) == 1,

il construit un tuple avec le résultat de la comparaison du tuple (1,) avec un entier et donc du retour False.

Au lieu de cela, lorsque vous affectez des variables, les deux tuples égaux sont comparés l'un à l'autre.

Tu peux essayer:

>>> x = 1,
>>> x
(1,)
mng
la source