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
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...
Answer
#1: Initial revision
## 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*.