Does Python have a ternary conditional operator?
Yes, it was added in version 2.5. The expression syntax is:
a if condition else b
First condition
is evaluated, then exactly one of either a
or b
is evaluated and returned based on the Boolean value of condition
. If condition
evaluates to True
, then a
is evaluated and returned but b
is ignored, or else when b
is evaluated and returned but a
is ignored.
This allows short-circuiting because when condition
is true only a
is evaluated and b
is not evaluated at all, but when condition
is false only b
is evaluated and a
is not evaluated at all.
For example:
>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'
Note that conditionals are an expression, not a statement. This means you can't use assignment statements or pass
or other statements within a conditional expression:
>>> pass if False else x = 3
File "<stdin>", line 1
pass if False else x = 3
^
SyntaxError: invalid syntax
You can, however, use conditional expressions to assign a variable like so:
x = a if True else b
Think of the conditional expression as switching between two values. It is very useful when you're in a 'one value or another' situation, but it doesn't do much else.
If you need to use statements, you have to use a normal if
statement instead of a conditional expression.
Keep in mind that it's frowned upon by some Pythonistas for several reasons:
- The order of the arguments is different from those of the classic
condition ? a : b
ternary operator from many other languages (such as C, C++, Go, Perl, Ruby, Java, JavaScript, etc.), which may lead to bugs when people unfamiliar with Python's "surprising" behaviour use it (they may reverse the argument order). - Some find it "unwieldy", since it goes contrary to the normal flow of thought (thinking of the condition first and then the effects).
- Stylistic reasons. (Although the 'inline
if
' can be really useful, and make your script more concise, it really does complicate your code)
If you're having trouble remembering the order, then remember that when read aloud, you (almost) say what you mean. For example, x = 4 if b > 8 else 9
is read aloud as x will be 4 if b is greater than 8 otherwise 9
.
Official documentation:
- Conditional expressions
- Is there an equivalent of C’s ”?:” ternary operator?
Python ? (conditional/ternary) operator for assignments
Python has such an operator:
variable = something if condition else something_else
Alternatively, although not recommended (see karadoc's comment):
variable = (condition and something) or something_else
How is ternary operator implemented in Python
Python doesn't have to convert anything, and couldn't if it wanted to.
The conditional expression is parsed by using the language grammar into an abstract syntax tree, which in turn is then compiled to bytecode. You can produce the AST by using the ast.parse()
function:
>>> import ast
>>> ast.parse('c = a if condition else b').body[0] # first statement in the tree
<_ast.Assign object at 0x10f05c550>
>>> ast.dump(ast.parse('c = a if condition else b').body[0])
"Assign(targets=[Name(id='c', ctx=Store())], value=IfExp(test=Name(id='condition', ctx=Load()), body=Name(id='a', ctx=Load()), orelse=Name(id='b', ctx=Load())))"
Note the ast.IfExp()
node in the AST produced for the assignment; this is a dedicated node for conditional expressions. It has test
, body
and orelse
parts to represent the 3 expressions that make up the condition, true and false parts. This is documented in the ast
module Abstract Grammar section:
expr = [...]
| [...]
| IfExp(expr test, expr body, expr orelse)
This shows that the type of each element is another expr
expression node.
The parse tree is then compiled to bytecode that uses the stack to conditionally jump to the right section based on the test; we can pass the AST produced by ast.parse()
directly to the compile()
function, after which the dis
module lets us look at a human-friendly form of the bytecode produced by compilation:
>>> import dis
>>> dis.dis(compile(ast.parse('c = a if condition else b'), '', 'exec'))
1 0 LOAD_NAME 0 (condition)
2 POP_JUMP_IF_FALSE 8
4 LOAD_NAME 1 (a)
6 JUMP_FORWARD 2 (to 10)
>> 8 LOAD_NAME 2 (b)
>> 10 STORE_NAME 3 (c)
12 LOAD_CONST 0 (None)
14 RETURN_VALUE
So if the condition is false, the interpreter loop jumps forward to instruction 8, otherwise instructions 4 and 6 are executed, with instruction 6 jumping forward to instruction 10 (so past the else
expression). The end result is that either instruction 4 or instruction 8 puts a new result on the top of the stack for STORE_NAME
to move to a variable.
An if
statement results in a different AST node, and the resulting bytecode happens to be very similar in that it too would use jumps. But the compiler treats them as distinct pieces of syntax, and it has to.
Expressions and statements are two very different fundamental building blocks of a programming language. Statements can contain expressions, but expressions can't contain statements, only other expressions. And expressions can produce a value (for the surrounding syntax to use), but statements can't. So Python has to treat conditional expressions very differently from statements, in that the grammar parser knows when to expect a statement and when an expression is allowed. If you transformed a conditional expression into a statement, you would not be able to ever use such an expression as part of a bigger expression!
Because an if
statement is not an expression, it doesn't return a value (as only expressions can produce a value), and so the resulting bytecode would not produce a value on the top of the stack to be used by the surrounding Python code (there is no c = if condition : ...
). if
statements contain a condition expression, and a suite, which must always consist of more statements (there is such a thing as an 'expression statement' to let you put just an expression in a statement, such as 1 + 1
on a single line), and those statements can 'do stuff' like assignments or return from a function, but nothing they do would ever make if
return something.
This is reflected in the AST node definition for if
statements:
stmt = [...]
| [...]
| If(expr test, stmt* body, stmt* orelse)
So for an If
node, test
is the only expression node, and body
and orelse
both consist of zero or more statements. The orelse
part would hold any elif ...:
tests as further If()
nodes, or any other type of statement to form an unconditional else:
. With zero-or-more elements, you can't expect a single result.
So this isn't unique to CPython, this applies to all Python implementations. The Python grammar is not an implementation detail.
Does Python have ternary conditional with elif?
You can chain the conditional operator, but it's not recommended, since it gets pretty hard to read. The associativity works the way you expect (like every language aside from PHP):
a = b if c == d else i if e == f else j
which means in English "assign b to a if c equals d, otherwise, assign i if e equals f, and j if not."
Conditional expression/ternary operator
First note that all these give the minimum value of a
and b
:
a, b = 10, 20
res1 = (b, a)[a < b] # 10
res2 = {True: a, False: b}[a < b] # 10
res3 = (lambda: b, lambda: a)[a < b]() # 10
We can consider these in turn:
res1
constructs atuple
of 2 integers.a < b
returns a Boolean value, in this caseTrue
. In Python,True == 1
, asbool
is a subclass ofint
. Finally,[]
is syntactic sugar for__getitem__
, which is the method called for positional indexing. Since Python starts counting from0
, the first index isa
. You can also confirm this yourself:(b, a).__getitem__(1)
returns10
.res2
constructs a dictionary mapping Boolean values toa
&b
. Calling__getitem__
on adict
object returns the value for a given key. Here the key, as before, isTrue
. Since the dictionary mapsTrue
toa
, this is the value returned.res3
constructs a tuple of anonymous (lambda
) functions, each returning scalars, namelyb
anda
. As perres1
, an item can be extracted from a tuple via integer indexing. The only additional requirement is to actually call thelambda
functions via()
.
Note none of these operate the same way as the ternary operator which is applied at compile time (see comments) via an in-line if
/ else
:
res4 = a if a < b else b
Ternary using pass keyword python
Point 1: Are your sure your condition is right? Because if True
will always be True
and code will never go to else
block.
Point 2: pass
and continue
are not expressions or values, but a action instead You can not use these is one line. Instead if you use, 3 if x else 4
<-- it will work
Does Python have a ternary conditional operator?
Yes, it was added in version 2.5. The expression syntax is:
a if condition else b
First condition
is evaluated, then exactly one of either a
or b
is evaluated and returned based on the Boolean value of condition
. If condition
evaluates to True
, then a
is evaluated and returned but b
is ignored, or else when b
is evaluated and returned but a
is ignored.
This allows short-circuiting because when condition
is true only a
is evaluated and b
is not evaluated at all, but when condition
is false only b
is evaluated and a
is not evaluated at all.
For example:
>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'
Note that conditionals are an expression, not a statement. This means you can't use assignment statements or pass
or other statements within a conditional expression:
>>> pass if False else x = 3
File "<stdin>", line 1
pass if False else x = 3
^
SyntaxError: invalid syntax
You can, however, use conditional expressions to assign a variable like so:
x = a if True else b
Think of the conditional expression as switching between two values. It is very useful when you're in a 'one value or another' situation, but it doesn't do much else.
If you need to use statements, you have to use a normal if
statement instead of a conditional expression.
Keep in mind that it's frowned upon by some Pythonistas for several reasons:
- The order of the arguments is different from those of the classic
condition ? a : b
ternary operator from many other languages (such as C, C++, Go, Perl, Ruby, Java, JavaScript, etc.), which may lead to bugs when people unfamiliar with Python's "surprising" behaviour use it (they may reverse the argument order). - Some find it "unwieldy", since it goes contrary to the normal flow of thought (thinking of the condition first and then the effects).
- Stylistic reasons. (Although the 'inline
if
' can be really useful, and make your script more concise, it really does complicate your code)
If you're having trouble remembering the order, then remember that when read aloud, you (almost) say what you mean. For example, x = 4 if b > 8 else 9
is read aloud as x will be 4 if b is greater than 8 otherwise 9
.
Official documentation:
- Conditional expressions
- Is there an equivalent of C’s ”?:” ternary operator?
Python ternary object attribute evaluated out of order?
Ok so the reason why the 2nd one works is because a is set to None and it goes to the first if statement and skips the else statement since the first if statement is true. If u were to say like:
a=None
if a is not None:
b=0
else:
b=a.val
This would get an error: AttributeError: 'NoneType' object has no attribute 'val'
.
A Nonetype doesn't have a .val
so I am not sure how you got that from?
a = None
print(a.val)
AttributeError: 'NoneType' object has no attribute 'val'
Either way, if you want to have a ternary operator(btw ternary operator don't exist in python) so a similar way of doing this would be something like:
(I am gonna assume that a.val is a class maybe?)
a = None
b = a.val if a is None else 0
The reason why b = (a.val, 0)[a is None]
gives you an error is cause
if you think about it you are creating a tuple... So python first creates a tuple then does the [a is None]
part. a.val
is undefined so it will give you an error. If you try to do b = (a.val,0)
(notice I remove the index part) it will give you the same error since first it creates a tuple.
b = (a.val,0)[a is None)
is equalivent to:
b = (a.val,0)
b[a is None]
We know that a.val is undefined so it automatically gives you an attribute error.. so the index part isn't the error. It's your tuple part.
Hope this makes sense!
Related Topics
System-Wide Mutex in Python on Linux
Using Global Variables in a Function
How to Remove Duplicates from a List, While Preserving Order
Replacements For Switch Statement in Python
Remap Values in Pandas Column With a Dict, Preserve Nans
How to Concatenate Items in a List to a Single String
How to Add Value Labels on a Bar Chart
Switch to an Iframe Through Selenium and Python
Getting the Name of a Variable as a String
Post Values from an HTML Form and Access Them in a Flask View
How to Make a Python Script Run Like a Service or Daemon in Linux
Force Python to Use an Older Version of Module (Than What I Have Installed Now)
When Should I (Not) Want to Use Pandas Apply() in My Code
Error "Microsoft Visual C++ 14.0 Is Required (Unable to Find Vcvarsall.Bat)"