14 votes

Pourquoi la syntaxe "not(True) * True" est-elle valide, contrairement à "True * not(True)" ?

Est-ce une conséquence de l'ordre hiérarchique des opérateurs dans Python ?

not(True) * True
# False
True * not(True)
# SyntaxError: invalid syntax

21voto

Karl Knechtel Points 24349

Est-ce une conséquence de l'ordre hiérarchique des opérateurs dans Python ?

Oui (bien que le terme habituel soit préséance de l'opérateur ). Résumer et simplifier :

  1. not n'est pas une fonction ; c'est un opérateur . Par conséquent, il n'est pas nécessaire d'écrire des parenthèses pour not (True) En fait, ils ne font rien ici. Tout ce qui se passe, c'est que les parenthèses sont traitées comme des regroupement parenthèses - (True) est évaluée avant toute autre chose, devenant ainsi True . Considérons donc les exemples sans les parenthèses.

  2. not True * True moyens not (True * True) . Il s'agit de no moyen (not True) * True en raison de la préséance de l'opérateur. Cela a été conçu :

    >>> not 1 * 0
    True
    >>> not (1 * 0)
    True
    >>> (not 1) * 0
    0

    Les développeurs ont pensé qu'il serait inattendu d'écrire quelque chose comme not 1 * 0 et obtenir un résultat entier, et inattendu d'écrire not devant une opération mathématique et de faire en sorte que l'opération mathématique ne soit pas prise en compte dans le calcul de l'impôt sur le revenu. not ne s'appliquent qu'au premier élément de cette expression.

  3. En raison de cette même préséance de l'opérateur, True * not True est une erreur de syntaxe. Python analyse l'élément not par lui-même en tant que partie droite de la * La mise en place d'un système de gestion de l'information n'a pas encore abouti. not True ensemble. True * not est manifestement absurde. Ou encore, une autre façon de voir les choses : " not suivi d'une expression" ne figure pas dans la liste des "choses qui peuvent être un opérande de * ".

    Ceci est peut-être surprenant car le autres opérateur unaire couramment utilisé, - (c'est-à-dire la négation unaire), n'a pas ce problème. Mais c'est parce que la préséance est inversée : la négation unaire est traitée avant la multiplication, et non après.

    Il en va de même pour and y or combinaisons :

    >>> 3 * 5 and 1 # 3 * 5 is evaluated first
    1
    >>> 3 * (5 and 1)
    3
    >>> 3 or 1 * 5 # 1 * 5 is evaluated first, even though it comes later
    3
    >>> (3 or 1) * 5
    15

11voto

user2357112 Points 37737

Il s'agit d'une question de préséance et de la manière dont la préséance est mise en œuvre.

* a une priorité plus élevée que not Dans la grammaire Python, il existe une hiérarchie de types d'expression, structurée de manière à ce que les opérateurs de priorité supérieure puissent être l'opérateur "racine" d'un argument d'un opérateur de priorité inférieure, mais pas l'inverse.

Par exemple, le règle de grammaire pour les expressions multiplicatives est

term[expr_ty]:
    | a=term '*' b=factor { _PyAST_BinOp(a, Mult, b, EXTRA) }
    | a=term '/' b=factor { _PyAST_BinOp(a, Div, b, EXTRA) }
    | a=term '//' b=factor { _PyAST_BinOp(a, FloorDiv, b, EXTRA) }
    | a=term '%' b=factor { _PyAST_BinOp(a, Mod, b, EXTRA) }
    | a=term '@' b=factor { CHECK_VERSION(expr_ty, 5, "The '@' operator is", _PyAST_BinOp(a, MatMult, b, EXTRA)) }
    | factor

term est la règle de grammaire pour les expressions multiplicatives. Les 5 premières options de cette règle consistent en un opérateur de priorité multiplicative au milieu, un autre opérateur de priorité multiplicative au milieu, un autre opérateur de priorité multiplicative au milieu et un autre opérateur de priorité multiplicative au milieu. term à gauche de l'opérateur, et un factor à droite, où factor est la règle de la classe d'opérateurs immédiatement supérieure. La 6e option est simplement une factor .

Structurer la grammaire de cette manière permet de s'assurer que l'arbre syntaxique analysé correspond toujours à la structure donnée par la précédence des opérateurs, mais cela signifie également que les opérateurs de précédence inférieure ne peuvent pas être l'opérateur "racine" d'un argument d'un opérateur de précédence supérieure, même lorsque l'expression semblerait non ambiguë. Aucune règle de grammaire n'autorise un opérateur not comme argument d'une expression * l'expression.

(Les règles de grammaire pour la plupart des expressions suivent la structure ci-dessus, mais il y a des exceptions. Par exemple, les règles de grammaire pour les parenthèses ne suivent pas la structure "pas d'opérateurs de rang inférieur dans les expressions de rang supérieur", ce qui explique que l'on puisse écrire des choses comme 3 * (4 + 5) . L'exponentiation est une autre exception - ** se lie plus étroitement qu'un unaire + / - / ~ à gauche, mais pas à droite, de sorte que les règles relatives aux ** et unaire + / - / ~ ne suivent pas une hiérarchie de préséance claire).

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