Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Does Python have a "ternary operator" (conditional evaluation operator like "?:" in other languages)?

+4
−1

Sometimes code needs to assign (or otherwise use) a value that depends on some condition. The naive approach is to use explicit branching, which in Python would look like:

if some_condition():
    a_variable = condition_value
else:
    a_variable = not_condition_value

However, this seems needlessly verbose, and is not DRY - the assignment syntax is repeated.

Many other popular languages support some way to write an expression that evaluates to either of two stated options, depending on the condition. Typically this uses what is often called a "ternary conditional operator" or just "the ternary operator"[1], commonly written using ? and : symbols - so it looks like:

a_variable = some_condition() ? condition_value : not_condition_value

Generally this operator is short-circuiting: i.e., if condition_value and/or not_condition_value are more complex expressions, only the necessary one is evaluated according to the some_condition() result.

Does Python have any syntax like this?


  1. Here, "ternary" simply means that there are three operands; but this operator is often referred to as "the" ternary operator because it is typically the only one in the language with that property. ↩︎

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

2 answers

+2
−0

The Python ternary "operator" is if and else:

x = 1 if some_condition else 0

In Python, this is called a "conditional expression" rather than an operator, and the documentation explains it: https://docs.python.org/3.12/reference/expressions.html?highlight=ternary#conditional-expressions

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

0 comment threads

+5
−0

How to do it

Yes, Python has an equivalent operator. However, it's spelled with keywords rather than punctuation, and it uses a different order of operands. It looks like:

condition_value if some_condition() else not_condition_value

This creates an expression, so the result can then be assigned to a variable etc. It's officially labelled as a "conditional expression" in the Python grammar. Its semantics cannot be changed using operator overloading.

The difference in order is a deliberate part of the design. There was some controversy over it at the time, but it appears to be intended that the reordered expression reads naturally and emphasizes the common case: "the result shall be condition_value, if some_condition() is met; else it will be not_condition_value.

Like with ?: in other languages, the operands here will be evaluated at most once, and the overall process will short-circuit. That is, if condition_value and/or not_condition_value are instead more complex expressions, only the one that will actually be used gets evaluated.

Conditional assignment

Sometimes people want to use this syntax to make a variable assignment only when a condition is met, and leave the variable alone otherwise.

This can be implemented by just using the existing value for the false condition:

a_variable = condition_value if some_condition() else a_variable

However, this is still not DRY, and it's not very intuitive.

It is generally considered better to just use an explicit if statement here:

if some_condition():
    a_variable = condition_value

There is no real value in complicating it any further.

Just for completeness, it's possible to get something like this in Python 3.8 and onward, by abusing the assignment expression for the true condition and using an ignored dummy value for the false condition:

>>> (a := "it was true") if True else None
'it was true'
>>> a
'it was true'
>>> (a := "it was true") if False else None # evaluates to None
>>> a # still has the old value
'it was true'

This approach could also use an assignment expression could be used for both branches, to assign to different variables. However, this sort of code is confusing and offers no real practical benefit.

Other common attempts will not work.

Since this conditional expression is an expression, its operands must also be valid expressions. It can't use non-expression statements:

>>> pass if True else "it wasn't true"
  File "<stdin>", line 1
    pass if True else "it wasn't true"
         ^^
SyntaxError: invalid syntax

Here, the pass is invalid, as it is a statement.

Like with ?: in other languages, a result must be provided for both cases:

>>> a = "it was true" if True
  File "<stdin>", line 1
    a = "it was true" if True
        ^^^^^^^^^^^^^^^^^^^^^
SyntaxError: expected 'else' after 'if' expression

(Older versions of Python may give less helpful error messages.)

Other approaches

Very old legacy code from before Python 2.5 - or code written by people who learned very old idioms and haven't updated - may try to work around the lack of such syntax support, even though the support is actually there.

and-or combination

An old idiom exploits the semantics of and and or operators, which evaluate to either of their operands rather than to a boolean value. Thus, one may see:

some_condition() and condition_value or not_condition_value

This is in some sense a natural extension of another old idiom using or to specify "default" values.

This does short-circuit as desired, and evaluates the operands only once; and parentheses are not needed because the and takes precedence over or. However, this breaks when condition_value is falsy - since some_condition() and condition_value will then also be falsy, the result is not_condition_value.

Some code may work around this limitation by wrapping the results in single-element lists (or tuples), so that the values are always truthy, and then extracting what is needed:

# This is safe even if condition_value is False, None, etc.
[some_condition() and [condition_value] or [not_condition_value]][0]

However, this looks awkward, and it's hard to remember the extra steps.

Selection by using the conditional as an index

Another approach is to put the two options for the result into a list (anything that can be indexed by an integer would work), and then use the condition to index into that list. This works by itself when the condition value is a boolean:

# `some_condition()` should return True or False specifically
[not_condition_value, condition_value][some_condition()]

If necessary, the condition value could just be coerced first:

# This way is safer
[not_condition_value, condition_value][bool(some_condition())]

The idea is that False is equivalent to 0 and True is equivalent to 1 when used as an index. (Further adjustments would be required to use a dictionary to store the possible results - this is left as an exercise.)

This can sometimes be a natural solution, that can be seen as a special case of a more general "dispatching" approach (where some_condition() could have multiple relevant values, and is used to select the right result). However, keep in mind that this does not short-circuit.

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »