1

I know the conditional expression in Python is X if C else Y, but I got some problems in using it.

I have two codes to be compared.

Code 1:

def fun(p):
    if len(p) >= 2:
        p[1] = 'Ok'
    else:
        p.append('Ok')
p = [1]
fun(p)
print p

Output of code 1:

[1, 'Ok']

Code 2:

def fun(p):
    (p[1] = 'Ok') if (len(p) >= 2) else p.append('OK')

p = [1]
fun(p)
print p

Output of code 2:

    (p[1] = 'Ok') if (len(p) >= 2) else p.append('OK')
      ^
SyntaxError: invalid syntax

I know in code 1, whose format is "if C : X else: Y", the evaluation order is:

  1. C
  2. X
  3. Y

Code 2 throws a syntax error, the reason may be p[1] doesn't exist. So I guess the format "X if C else Y" is evaluated as follows:

  1. X
  2. C
  3. Y

But that is only my guess. does anyone know the real reason why code 2 is wrong while code 1 is right?

Huo
  • 798
  • 3
  • 12
  • 22
  • 2
    Note that assignments are statements and can't appear in expression contexts. That is the reason for the error in Code 2. – Dan D. Mar 22 '12 at 09:07

3 Answers3

4

The reason you have a SyntaxError is because Python differentiates between statements and expressions.

Assignments, like

p[1] = 'Ok'

are statements and can't be part of an expression, including the conditional expression. See What is the difference between an expression and a statement in Python? for more info.

Order of evaluation doesn't come into it -- SyntaxErrors happen before any code is evaluated, when its being parsed.

In both if statements and conditional expressions, The order of evaluations is ether

  1. Condition
  2. True Statement

or

  1. Condition
  2. False Statement

So, in

if condition:
    true_statement
else:
    false_statement

or

true_statement if condition else false_statement

only the true or the fase statement is evaluated, depending on the truthiness of the condition.

Community
  • 1
  • 1
agf
  • 171,228
  • 44
  • 289
  • 238
1

Assignment is no expression (others pointed that out). Hence the syntax error.

Regarding your question concerning evaluation order:

In if-else expressions(!) first the condition operand is evaluated, then either the then-operand (leftmost) or the else-operand (rightmost) is evaluated. The other operand is not evaluated.

In or-expressions the operands are evaluated from leftmost to rightmost (a or b or c or d or ...) but only until one is found whose Boolean value is True. The remaining expressions are not evaluated.

In and-expressions the operands are evaluated from leftmost to rightmost (a and b and c and d and ...) but only until one is found whose Boolean value is False. The remaining expressions are not evaluated.

Inner expressions are evaluated before outer expressions (of course): third(second(first()))

In all other cases (a() + b(), f(g(), h()), a[b[c]] = d() + e) the order is defined as specified. Typically it's left-to-right except for assignment (where it is right before left).

Alfe
  • 56,346
  • 20
  • 107
  • 159
0

As Dan D. points out, you can't have statements in expression contexts.

In the interest of learning -- I do not recommend doing it this way -- I'll show you how you could use the inline X if C else Y to accomplish what you're attempting to do:

def fun(p):
    p.__setitem__(1, 'Ok') if len(p) >= 2 else p.append('OK')

As you can see, your fist version is much more readable.

Lauritz V. Thaulow
  • 49,139
  • 12
  • 73
  • 92
  • Is readability the only reason why you wouldn't do this? (It seems impolite to use the ternary operator syntax for a side effect.) – Li-aung Yip Mar 22 '12 at 09:20
  • @Li-aung Of course you're right -- this is misusing the ternary operator since we're just throwing away the answer (which is either `None` or `None`). But at least we're explicit about it -- there's no doubt that this is done expressly for the side effects. – Lauritz V. Thaulow Mar 22 '12 at 09:23
  • @lazyr Thanks for giving me another solution. – Huo Mar 22 '12 at 09:29