Skip to content

Syntax: Mismatching order of conditional expression evaluation #111135

@awwright

Description

@awwright

Bug report

Bug description:

The syntax for a conditional expression changes depending on the context the logic is found in: If in a conditional expression, or if in a statement.

This can be verified by checking the full grammar specification, which uses an if symbol in two distinct places, once in the "if_stmt" production (itself referenced as an alternative in the "compound_stmt" production) and again as one of a few alternatives for the "expression" production. This would ordinarily be an acceptable way to factor the grammar, if not for the fact that the order of evaluation is inconsistent: the "if_stmt" production accepts expressions in "test, then, else" order and the "expression" production accepts statements in the "then, test, else" order. Unsurprisingly, this is confusing.

And this also violates a long-standing expectation that evaluation happens in a defined order; if I have any two expressions a and b, in that order in a file, the result of b should never impact the evaluation of a, unless a could sometimes impact b (in which case the rule is ambiguous).

Here, when reading the expression production disjunction 'if' disjunction 'else' expression, that ordering suggests that the first "disjunction" would be evaluated first, and the value will affect the execution of the second disjunction.

But in the actual execution, this is not the case:

def x(n):
        print(n);
        return n;
x(x(1) if x(2) else x(3));

In this file, I should expect to see 1 be the first line of output, but surprisingly it's 2: It's skipping over the evaluation of x(1), running x(2), then deciding based on the return value to evaluate x(1).

This mistake appears to have been introduced in https://mail.python.org/pipermail/python-dev/2005-September/056846.html then formalized in https://peps.python.org/pep-0308/

CPython versions tested on:

3.11

Operating systems tested on:

macOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions