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.

Post History

77%
+5 −0
Q&A Does Python have a "ternary operator" (conditional evaluation operator like "?:" in other languages)?

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...

posted 11mo ago by Karl Knechtel‭

Answer
#1: Initial revision by user avatar Karl Knechtel‭ · 2023-12-01T23:12:20Z (11 months ago)
## How to do it

Yes, Python [has an equivalent operator](https://docs.python.org/3/faq/programming.html#is-there-an-equivalent-of-c-s-ternary-operator). However, it's spelled with keywords rather than punctuation, and it uses a different order of operands. It looks like:
```python
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](https://docs.python.org/3/reference/expressions.html#conditional-expressions). 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:**
```python
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:
```python
>>> (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:
```python
>>> 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:
```python
>>> 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:
```python
# 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:
```python
# `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:
```python
# 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*.