6670

If Python does not have a ternary conditional operator, is it possible to simulate one using other language constructs?

Georgy
  • 6,348
  • 7
  • 46
  • 58
Devoted
  • 90,341
  • 41
  • 85
  • 110
  • 161
    In the Python 3.0 official documentation referenced in a comment above, this is referred to as "conditional_expressions" and is very cryptically defined. That documentation doesn't even include the term "ternary", so you would be hard-pressed to find it via Google unless you knew exactly what to look for. The [version 2 documentation](http://docs.python.org/2/reference/expressions.html#conditional-expressions) is somewhat more helpful and includes a link to ["PEP 308"](http://www.python.org/dev/peps/pep-0308/), which includes a lot of interesting historical context related to this question. – Brent Bradburn Jan 10 '13 at 05:57
  • 4
    Though Pythons older than 2.5 are slowly drifting to history, here is a list of old pre-2.5 ternary operator tricks: ["Python Idioms", search for the text 'Conditional expression'](http://c2.com/cgi/wiki?PythonIdioms) . [Wikipedia](http://en.wikipedia.org/wiki/Ternary_operation#Python) is also quite helpful Ж:-) – ジョージ May 26 '11 at 00:48
  • 32
    "ternary" (having three inputs) is a consequential property of this impelmentation, not a defining property of the concept. eg: SQL has `case [...] { when ... then ...} [ else ... ] end` for a similar effect but not at all ternary. – user313114 Dec 15 '14 at 21:14
  • 11
    also ISO/IEC 9899 (the C programming language standard) section 6.5.15 calls it the "the condtitional operator" – user313114 Dec 15 '14 at 21:20
  • 10
    Wikipedia covers this thoroughly in the article "[?:](https://en.wikipedia.org/wiki/%3F:#Python)". – HelloGoodbye Jun 09 '16 at 08:11
  • 1
    It is mentioned here https://docs.python.org/3/faq/programming.html#is-there-an-equivalent-of-c-s-ternary-operator, but not mentioned in Python Standard Library – sdaffa23fdsf Mar 14 '18 at 04:20
  • 11
    In the years since nobar's comment the [conditional expression documentation](https://docs.python.org/3/reference/expressions.html#conditional-expressions) has been updated to say _Conditional expressions (sometimes called a “ternary operator”)..._ – Scott Martin Aug 15 '18 at 13:25
  • 1
    I sometimes wonder how it is possible that a yes or no question gets 26 answers – Kaan E. Aug 22 '20 at 02:58
  • @KaanE. and most of all being copy-paste of each other with different comments. So the value is in the comments... Anyway as of 2020 the comprehensive answer is in the ['Ternary Operators'](https://book.pythontips.com/en/latest/ternary_operators.html) documentation: "*Ternary operators are more commonly known as conditional expressions [...] they became a part of Python in version 2.4.*" – mins Oct 25 '20 at 16:53

27 Answers27

7715

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, it but 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:

wjandrea
  • 16,334
  • 5
  • 30
  • 53
Vinko Vrsalovic
  • 244,143
  • 49
  • 315
  • 361
  • 310
    The order may seems strange for coders however `f(x) = |x| = x if x > 0 else -x` sounds very natural to mathematicians. You may also understand it as do A in most case, except when C then you should do B instead... – yota Jan 25 '16 at 15:07
  • 143
    Be careful with order of operations when using this. For example, the line `z = 3 + x if x < y else y`. If `x=2` and `y=1`, you might expect that to yield 4, but it would actually yield 1. `z = 3 + (x if x > y else y)` is the correct usage. – Kal Zekdor Mar 06 '16 at 09:23
  • 14
    The point was if you want to perform additional evaluations *after* the conditional is evaluated, like adding a value to the result, you'll either need to add the additional expression to both sides (`z = 3 + x if x < y else 3 + y`), or group the conditional (`z = 3 + (x if x < y else y)` or `z = (x if x < y else y) + 3`) – Kal Zekdor Apr 15 '16 at 00:36
  • 1
    what if there are multiple conditions ? – MrGeek May 26 '17 at 15:31
  • @MrGeek, you could group the boolean expressions. "foo" if (bool or bool && bool or etc) else "bar" – Dimesio Aug 09 '17 at 06:08
  • @Dimesio I meant something like if (c1) a1 elif (c2) a2 elif ... else a(n). – MrGeek Aug 09 '17 at 09:17
  • 5
    @MrGeek, I see what you mean, so you would basically be nesting the operations: ` "foo" if Bool else ("bar" if Bool else "foobar") ` – Dimesio Aug 11 '17 at 00:04
  • 5
    Programmers need precise correct formulation even more than mathematician, because in mathematics there is always a resort to underlying concepts. A convincing argument is the % operator, mimicking the way "mod" is used in math would have been a disaster. So no, I don't accept your argument. It is like adhering to imperial units. Groetjes Albert – Albert van der Horst Jun 17 '18 at 12:50
  • For the expression: 'x and y' and 'x or y' and their return values I recommend checking https://docs.python.org/3/reference/expressions.html#boolean-operations and also the other post: https://stackoverflow.com/questions/3181901/python-boolean-expression-and-or/3181946#3181946 – BeMyGuestPlease Sep 08 '19 at 15:02
  • 2
    @KalZekdor I read that and expected 1... It took me a few seconds to see how you had to read it to make 4 a possibility. – Baldrickk Oct 10 '19 at 13:45
  • Go doesn't have ternary operator, bro. – QtRoS Jan 30 '20 at 11:18
  • Nice explanation, but short circuiting doesn't mean what you think it means - it means that the rest of the *condition* isn't evaluated if the 'truthiness' of the entire condition can be decided early. Statement 'b' is never evaluated even in languages without short circuiting. Ex: if (arr != null && arr[0] = 1)... – Gerard ONeill Mar 09 '20 at 23:35
865

You can index into a tuple:

(falseValue, trueValue)[test]

test needs to return True or False.
It might be safer to always implement it as:

(falseValue, trueValue)[test == True]

or you can use the built-in bool() to assure a Boolean value:

(falseValue, trueValue)[bool(<expression>)]
jesterjunk
  • 2,074
  • 17
  • 17
Landon Kuhn
  • 61,957
  • 42
  • 100
  • 130
  • 644
    Note that this one always evaluates everything, whereas the if/else construct only evaluates the winning expression. – SilverbackNet Feb 04 '11 at 02:25
  • 132
    `(lambda: print("a"), lambda: print("b"))[test==true]()` – Dustin Getz Mar 08 '12 at 19:31
  • 19
    It should be noted that what's within the `[]`s can be an arbitrary expression. Also, for safety you can explicitly test for truthiness by writing `[bool()]`. The `bool()` function has been around since v2.2.1. – martineau May 31 '12 at 18:20
  • 2
    Is this idiomatic in python? Seems confusing but maybe its convention – jskulski May 28 '15 at 20:57
  • Ugly is in the eye of the beholder, and I don't find this ugly at all. It concisely make elegant use of the fact that bool is a subclass of int and that Python indexes are 0-based. Admittedly, it's probably not the most efficient (as @SilverBackNet mentioned, both options are eval'd). However, this works perfectly for deciding between 1 of 2 strings as @Claudiu said - I use it for this all the time. For example: `'%d item%s to process!'%(num_items,('','s')[num_items > 1])` or `'Null hypothesis %s be rejected (p-val = %0.4f)'%(("can't",'must')[pval – Dr. Andrew Feb 19 '16 at 07:49
  • 12
    I've done a similar trick -- only once or twice, but done it -- by indexing into a dictionary with `True` and `False` as the keys: `{True:trueValue, False:falseValue}[test]` I don't know whether this is any less efficient, but it does at least avoid the whole "elegant" vs. "ugly" debate. There's no ambiguity that you're dealing with a boolean rather than an int. – JDM Mar 01 '16 at 18:43
  • 8
    [comparisons to singletons should always use is/is not instead of ==](https://www.python.org/dev/peps/pep-0008/#programming-recommendations) – Natecat May 02 '16 at 23:10
  • 2
    This trick may help avoid timing based attacks on algorithms if it always evaluates both possible results and avoids skipping code (an 'if' skips). – Breezer Nov 29 '17 at 13:59
  • @jskulski only in old python, before 2.5. Even then though, `if cond: [expression_1] else: [expression_2]` was more common – Baldrickk Oct 10 '19 at 13:48
  • 3
    It's a "cool" and interesting idea, no doubt. But real-life code should be easy to read and least error-prone. If one of my developers used this I would ask him to change it. Since IMHO this should not be used in production code, I have down voted the answer. – problemofficer Sep 23 '20 at 10:16
  • 1
    @JDM there's no ambiguity since `bool` is actually a subclass of `int`. And I'd argue that this answer and your variant of it are *both* ugly. – Mark Ransom Oct 19 '20 at 22:02
  • @MarkRansom, no argument that both are ugly (and no longer necessary) workarounds. However the answer does have a garden-path issue that my variation avoids. Put a tuple index in front of most anyone and I guarantee they will *not* immediately think, "oh, that variable must be representing a true/false value." They'll start by assuming it's an ordinal number and only after puzzling over the context will they realize its actual purpose. *That's* the ambiguity I'm talking about. – JDM Feb 23 '21 at 13:40
371

For versions prior to 2.5, there's the trick:

[expression] and [on_true] or [on_false]

It can give wrong results when on_true has a false boolean value.1
Although it does have the benefit of evaluating expressions left to right, which is clearer in my opinion.

1. Is there an equivalent of C’s ”?:” ternary operator?

Honest Abe
  • 7,434
  • 4
  • 45
  • 59
James Brady
  • 21,724
  • 7
  • 48
  • 56
  • 73
    The remedy is to use (test and [true_value] or [false_value])[0], which avoids this trap. – ThomasH Oct 21 '09 at 15:33
  • 7
    Ternary operator usually executes faster(sometimes by 10-25%). – volcano Jan 13 '14 at 07:52
  • 7
    @volcano Do you have source for me? – OrangeTux Aug 05 '14 at 12:30
  • 5
    @OrangeTux [Here's the disassembled code](https://tio.run/##bcoxCoAwEETRPqeY0kCwsPQ2kmR1QZOwWQtPH4OClQO/GV65dMtpao2PkkURuBoTIoEG76AOZGeDPol6SoKCCR5xrxH0yvVfeiwpdJ/lgVzH3kDWFOGk37Ha1m4). Using the method ThomasH suggested would be even slower. – mbomb007 Mar 19 '18 at 20:59
296

<expression 1> if <condition> else <expression 2>

a = 1
b = 2

1 if a > b else -1 
# Output is -1

1 if a > b else -1 if a < b else 0
# Output is -1
Edwin Pratt
  • 699
  • 8
  • 19
Simon Zimmermann
  • 3,528
  • 3
  • 19
  • 11
  • 88
    This one emphasizes the primary intent of the ternary operator: value selection. It also shows that more than one ternary can be chained together into a single expression. – Roy Tinker Oct 04 '10 at 21:14
  • 6
    @Craig , I agree, but it's also helpful to know what will happen when there are no parentheses. In real code, I too would tend to insert explicit parens. – Jon Coombs Dec 01 '14 at 21:30
  • Use: `return 3 if t > 10 else t/2` – mins Oct 25 '20 at 16:41
172

From the documentation:

Conditional expressions (sometimes called a “ternary operator”) have the lowest priority of all Python operations.

The expression x if C else y first evaluates the condition, C (not x); if C is true, x is evaluated and its value is returned; otherwise, y is evaluated and its value is returned.

See PEP 308 for more details about conditional expressions.

New since version 2.5.

jesterjunk
  • 2,074
  • 17
  • 17
Michael Burr
  • 311,791
  • 49
  • 497
  • 724
133

An operator for a conditional expression in Python was added in 2006 as part of Python Enhancement Proposal 308. Its form differ from common ?: operator and it's:

<expression1> if <condition> else <expression2>

which is equivalent to:

if <condition>: <expression1> else: <expression2>

Here is an example:

result = x if a > b else y

Another syntax which can be used (compatible with versions before 2.5):

result = (lambda:y, lambda:x)[a > b]()

where operands are lazily evaluated.

Another way is by indexing a tuple (which isn't consistent with the conditional operator of most other languages):

result = (y, x)[a > b]

or explicitly constructed dictionary:

result = {True: x, False: y}[a > b]

Another (less reliable), but simpler method is to use and and or operators:

result = (a > b) and x or y

however this won't work if x would be False.

A possible workaround is to make x and y lists or tuples as in the following:

result = ((a > b) and [x] or [y])[0]

or:

result = ((a > b) and (x,) or (y,))[0]

If you're working with dictionaries, instead of using a ternary conditional, you can take advantage of get(key, default), for example:

shell = os.environ.get('SHELL', "/bin/sh")

Source: ?: in Python at Wikipedia

Chrisji
  • 301
  • 2
  • 13
kenorb
  • 118,428
  • 63
  • 588
  • 624
  • 1
    `result = {1: x, 0: y}[a > b]` is another possible variant (`True` and `False` are actually integers with values `1` and `0`) – Walter Tross Feb 09 '19 at 18:07
103

Unfortunately, the

(falseValue, trueValue)[test]

solution doesn't have short-circuit behaviour; thus both falseValue and trueValue are evaluated regardless of the condition. This could be suboptimal or even buggy (i.e. both trueValue and falseValue could be methods and have side-effects).

One solution to this would be

(lambda: falseValue, lambda: trueValue)[test]()

(execution delayed until the winner is known ;)), but it introduces inconsistency between callable and non-callable objects. In addition, it doesn't solve the case when using properties.

And so the story goes - choosing between 3 mentioned solutions is a trade-off between having the short-circuit feature, using at least Зython 2.5 (IMHO not a problem anymore) and not being prone to "trueValue-evaluates-to-false" errors.

Georgy
  • 6,348
  • 7
  • 46
  • 58
gorsky
  • 1,272
  • 1
  • 11
  • 20
  • 3
    While the tuple of lambdas trick works, it takes roughly 3x as long as the ternary operator. It's only likely to be a reasonable idea if it can replace a long chain of `if else if`. – Perkins Oct 11 '18 at 17:34
80

Ternary Operator in different programming Languages

Here I just try to show some important difference in ternary operator between a couple of programming languages.

Ternary Operator in Javascript

var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0

Ternary Operator in Ruby

a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0

Ternary operator in Scala

val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0

Ternary operator in R programming

a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0

Ternary operator in Python

a = 1 if True else 0
# 1
b = 1 if False else 0
# 0
tchrist
  • 74,913
  • 28
  • 118
  • 169
Simplans
  • 1,993
  • 1
  • 20
  • 22
  • 15
    This [blogger found python's ternary operator to be unnecessarily different than most other languages](https://archive.is/yqwSh). – JamesThomasMoon Feb 15 '17 at 23:08
  • 7
    It may sound opinionated; but what it essentially says is that it the Python syntax is likely to be understood by a person who never saw a ternary operator, while very few people will understand the more usual syntax unless they have been told first what it means. – fralau Jan 10 '18 at 17:12
  • 2
    Algol68: a=.if. .true. .then. 1 .else. 0 .fi. This may be expressed also a=(.true.|1|0) As usual Algol68 is an improvement over its successors. – Albert van der Horst Jun 17 '18 at 12:55
  • something simple as `print a || ''` in ruby is pita in python `print a if a is not None else 'alt text'` – Varun Garg Nov 05 '20 at 08:44
  • @VarunGarg But of course you can say `print(a or 'alt text')` in Python. – lenz Nov 15 '20 at 20:24
66

For Python 2.5 and newer there is a specific syntax:

[on_true] if [cond] else [on_false]

In older Pythons a ternary operator is not implemented but it's possible to simulate it.

cond and on_true or on_false

Though, there is a potential problem, which if cond evaluates to True and on_true evaluates to False then on_false is returned instead of on_true. If you want this behavior the method is OK, otherwise use this:

{True: on_true, False: on_false}[cond is True] # is True, not == True

which can be wrapped by:

def q(cond, on_true, on_false)
    return {True: on_true, False: on_false}[cond is True]

and used this way:

q(cond, on_true, on_false)

It is compatible with all Python versions.

Paolo
  • 16,171
  • 20
  • 78
  • 110
  • 2
    The behaviour is not identical - `q("blob", on_true, on_false)` returns `on_false`, whereas `on_true if cond else on_false` returns `on_true`. A workaround is to replace `cond` with `cond is not None` in these cases, although that is not a perfect solution. –  Sep 26 '12 at 09:09
  • 5
    Why not `bool(cond)` instead of `cond is True`? The former checks the truthiness of `cond`, the latter checks for pointer-equality with the `True` object. As highlighted by @AndrewCecil, `"blob"` is truthy but it `is not True`. – Jonas Kölker Nov 11 '13 at 16:11
  • Wow, that looks really hacky! :) Technically, you can even write `[on_false, on_True][cond is True]` so the expression becomes shorter. – Arseny Feb 24 '14 at 11:51
  • There is no short circuit in this answer. If on_true and on_false are expensive to call this is a bad answer. – Hucker Mar 28 '19 at 14:08
47

You might often find

cond and on_true or on_false

but this lead to problem when on_true == 0

>>> x = 0
>>> print x == 0 and 0 or 1 
1
>>> x = 1
>>> print x == 0 and 0 or 1 
1

where you would expect for a normal ternary operator this result

>>> x = 0
>>> print 0 if x == 0 else 1 
0
>>> x = 1
>>> print 0 if x == 0 else 1 
1
42

Does Python have a ternary conditional operator?

Yes. From the grammar file:

test: or_test ['if' or_test 'else' test] | lambdef

The part of interest is:

or_test ['if' or_test 'else' test]

So, a ternary conditional operation is of the form:

expression1 if expression2 else expression3

expression3 will be lazily evaluated (that is, evaluated only if expression2 is false in a boolean context). And because of the recursive definition, you can chain them indefinitely (though it may considered bad style.)

expression1 if expression2 else expression3 if expression4 else expression5 # and so on

A note on usage:

Note that every if must be followed with an else. People learning list comprehensions and generator expressions may find this to be a difficult lesson to learn - the following will not work, as Python expects a third expression for an else:

[expression1 if expression2 for element in iterable]
#                          ^-- need an else here

which raises a SyntaxError: invalid syntax. So the above is either an incomplete piece of logic (perhaps the user expects a no-op in the false condition) or what may be intended is to use expression2 as a filter - notes that the following is legal Python:

[expression1 for element in iterable if expression2]

expression2 works as a filter for the list comprehension, and is not a ternary conditional operator.

Alternative syntax for a more narrow case:

You may find it somewhat painful to write the following:

expression1 if expression1 else expression2

expression1 will have to be evaluated twice with the above usage. It can limit redundancy if it is simply a local variable. However, a common and performant Pythonic idiom for this use-case is to use or's shortcutting behavior:

expression1 or expression2

which is equivalent in semantics. Note that some style-guides may limit this usage on the grounds of clarity - it does pack a lot of meaning into very little syntax.

Aaron Hall
  • 291,450
  • 75
  • 369
  • 312
  • 1
    `expression1 or expression2` being similar and with the same drawbacks/positives as `expression1 || expression2` in javascript – JSDBroughton Feb 18 '16 at 13:05
  • 1
    Thanks, @selurvedu - it can be confusing until you get it straight. I learned the hard way, so your way might not be as hard. ;) Using if without the else, at the end of a generator expression or list comprehension will filter the iterable. In the front, it's a ternary conditional operation, and requires the else. Cheers!! – Aaron Hall May 27 '16 at 04:37
  • @AaronHall Although your use of metasyntactic `expressionN` for all instances is consistent, it might be easier to understand with naming that distinguished the conditional test expression from the two result expressions; eg, `result1 if condition else result2`. This is especially evident when nesting (aka chaining): `result1 if condition1 else result2 if condition2 else result3`. See how much better that reads this way? – tchrist Jan 26 '19 at 14:12
  • @tchrist thanks for the review - if you look at the revision history, this post currently has two revisions. Most of my other answers, especially the top ones, have been revisited again and again. This answer never gets my attention because the community wiki status gives me no credit for the content, and so I never see any votes on it. As I don't really have time for an edit on this right now, frog knows when it will come to my attention again in the future. I can see you've edited the top answer, so feel free to borrow/quote my material from this post in that one (and cite me if apropos!) – Aaron Hall Jan 26 '19 at 18:24
24

Simulating the python ternary operator.

For example

a, b, x, y = 1, 2, 'a greather than b', 'b greater than a'
result = (lambda:y, lambda:x)[a > b]()

output:

'b greater than a'
Sasikiran Vaddi
  • 1,439
  • 3
  • 17
  • 29
  • 1
    Why not simply `result = (y, x)[a < b]` Why do you uses `lambda` function **?** – Grijesh Chauhan Dec 27 '13 at 05:50
  • 6
    @GrijeshChauhan Because on "compliated" expressions, e. g. involving a function call etc., this would be executed in both cases. This might not be wanted. – glglgl Feb 13 '14 at 08:14
  • 1
    The use of `lambda` functions is an overkill for this question – jocerfranquiz Dec 14 '20 at 04:29
  • @GrijeshChauhan In short, this implements the so-called “**short-circuit evaluation**”. Generally, `P ? x : y` or `x if P else y` can be written as `(lambda:y, lambda:x)[P]()` — but I doubt it has better performance and thus its necessity. – SneezeFor16Min Jan 19 '21 at 10:11
23
a if condition else b

Just memorize this pyramid if you have trouble remembering:

     condition
  if           else
a                   b 
shivtej
  • 183
  • 5
  • 17
22

Ternary conditional operator simply allows testing a condition in a single line replacing the multiline if-else making the code compact.

Syntax :

[on_true] if [expression] else [on_false]

1- Simple Method to use ternary operator:

# Program to demonstrate conditional operator
a, b = 10, 20
# Copy value of a in min if a < b else copy b
min = a if a < b else b
print(min)  # Output: 10

2- Direct Method of using tuples, Dictionary, and lambda:

# Python program to demonstrate ternary operator
a, b = 10, 20
# Use tuple for selecting an item
print( (b, a) [a < b] )
# Use Dictionary for selecting an item
print({True: a, False: b} [a < b])
# lamda is more efficient than above two methods
# because in lambda  we are assure that
# only one expression will be evaluated unlike in
# tuple and Dictionary
print((lambda: b, lambda: a)[a < b]()) # in output you should see three 10

3- Ternary operator can be written as nested if-else:

# Python program to demonstrate nested ternary operator
a, b = 10, 20
print ("Both a and b are equal" if a == b else "a is greater than b"
        if a > b else "b is greater than a")

Above approach can be written as:

# Python program to demonstrate nested ternary operator
a, b = 10, 20
if a != b:
    if a > b:
        print("a is greater than b")
    else:
        print("b is greater than a")
else:
    print("Both a and b are equal") 
# Output: b is greater than a
Ali Hallaji
  • 1,738
  • 1
  • 18
  • 27
  • 1
    Note that the ternary operator is smaller (in memory) and faster than the nested if. Also, your nested `if-else` isn't actually a rewrite of the ternary operator, and will produce different output for select values of a and b (specifically if one is a type which implements a weird `__ne__` method). – Perkins Oct 11 '18 at 17:28
21

you can do this :-

[condition] and [expression_1] or [expression_2] ;

Example:-

print(number%2 and "odd" or "even")

This would print "odd" if the number is odd or "even" if the number is even.


The result :- If condition is true exp_1 is executed else exp_2 is executed.

Note :- 0 , None , False , emptylist , emptyString evaluates as False. And any data other than 0 evaluates to True.

Here's how it works:

if the condition [condition] becomes "True" then , expression_1 will be evaluated but not expression_2 . If we "and" something with 0 (zero) , the result will always to be fasle .So in the below statement ,

0 and exp

The expression exp won't be evaluated at all since "and" with 0 will always evaluate to zero and there is no need to evaluate the expression . This is how the compiler itself works , in all languages.

In

1 or exp

the expression exp won't be evaluated at all since "or" with 1 will always be 1. So it won't bother to evaluate the expression exp since the result will be 1 anyway . (compiler optimization methods).

But in case of

True and exp1 or exp2

The second expression exp2 won't be evaluated since True and exp1 would be True when exp1 isn't false .

Similarly in

False and exp1 or exp2

The expression exp1 won't be evaluated since False is equivalent to writing 0 and doing "and" with 0 would be 0 itself but after exp1 since "or" is used, it will evaluate the expression exp2 after "or" .


Note:- This kind of branching using "or" and "and" can only be used when the expression_1 doesn't have a Truth value of False (or 0 or None or emptylist [ ] or emptystring ' '.) since if expression_1 becomes False , then the expression_2 will be evaluated because of the presence "or" between exp_1 and exp_2.

In case you still want to make it work for all the cases regardless of what exp_1 and exp_2 truth values are, do this :-

[condition] and ([expression_1] or 1) or [expression_2] ;

Community
  • 1
  • 1
Natesh bhat
  • 7,780
  • 5
  • 52
  • 90
  • If you want to use that in the context of `x = [condition] and ([expression_1] or 1) or [expression_2]` and `expression_1` evaluates to false, `x` will be `1`, not `expression_1`. Use the accepted answer. – moi Oct 20 '17 at 06:37
21

One of the alternatives to Python's conditional expression

"yes" if boolean else "no"

is the following:

{True:"yes", False:"no"}[boolean]

which has the following nice extension:

{True:"yes", False:"no", None:"maybe"}[boolean_or_none]

The shortest alternative remains:

("no", "yes")[boolean]

but there is no alternative to

yes() if boolean else no()

if you want to avoid the evaluation of yes() and no(), because in

(no(), yes())[boolean]  # bad

both no() and yes() are evaluated.

Walter Tross
  • 10,629
  • 2
  • 31
  • 59
19

More a tip than an answer (don't need to repeat the obvious for the hundreth time), but I sometimes use it as a oneliner shortcut in such constructs:

if conditionX:
    print('yes')
else:
    print('nah')

, becomes:

print('yes') if conditionX else print('nah')

Some (many :) may frown upon it as unpythonic (even, ruby-ish :), but I personally find it more natural - i.e. how you'd express it normally, plus a bit more visually appealing in large blocks of code.

Tyler Jandreau
  • 4,060
  • 17
  • 40
Todor Minakov
  • 14,867
  • 2
  • 44
  • 49
  • 7
    I prefer `print( 'yes' if conditionX else 'nah' )` over your answer. :-) – frederick99 Aug 20 '17 at 06:07
  • That is if you want to `print()` in both cases - and it looks a bit more pythonic, I have to admit :) But what if the expressions/functions are not the same - like `print('yes') if conditionX else True` - to get the `print()` only in truthy `conditionX ` – Todor Minakov Oct 26 '17 at 11:40
  • To add to Frederick99's remark, another reason to avoid `print('yes') if conditionX else print('nah')` is that it gives a SyntaxError in Python2. – Thierry Lathuille Oct 21 '18 at 21:51
  • The only reason it gives a syntax error is because in Python 2 print is a statement - `print "yes"`, while in Python 3 it is a function - `print("yes")`. That can be resolved by either using it as a statement, or better - `from future import print_function`. – Todor Minakov Oct 22 '18 at 04:09
12

As already answered, yes there is a ternary operator in python:

<expression 1> if <condition> else <expression 2>

Additional information:

If <expression 1> is the condition you can use Short-cirquit evaluation:

a = True
b = False

# Instead of this:
x = a if a else b

# You could use Short-cirquit evaluation:
x = a or b

PS: Of course, a Short-cirquit evaluation is not a ternary operator but often the ternary is used in cases where the short circuit would be enough.

Frank
  • 1,329
  • 7
  • 19
10

Many programming languages derived from C usually have the following syntax of ternary conditional operator:

<condition> ? <expression1> : <expression2>

At first, the Python Benevolent Dictator For Life (I mean Guido van Rossum, of course) rejected it (as non-Pythonic style), since it's quite hard to understand for people not used to C language. Also, the colon sign : already has many uses in Python. After PEP 308 was approved, Python finally received its own shortcut conditional expression (what we use now):

<expression1> if <condition> else <expression2>

So, firstly it evaluates the condition. If it returns True, expression1 will be evaluated to give the result, otherwise expression2 will be evaluated. Due to Lazy Evaluation mechanics – only one expression will be executed.

Here are some examples (conditions will be evaluated from left to right):

pressure = 10
print('High' if pressure < 20 else 'Critical')

# Result is 'High'

Ternary operators can be chained in series:

pressure = 5
print('Normal' if pressure < 10 else 'High' if pressure < 20 else 'Critical')

# Result is 'Normal'

The following one is the same as previous one:

pressure = 5

if pressure < 20:
    if pressure < 10:
        print('Normal')
    else:
        print('High')
else:
    print('Critical')

# Result is 'Normal'

Hope this helps.

jamesfacts
  • 321
  • 2
  • 9
Andy Fedoroff
  • 26,838
  • 8
  • 85
  • 144
8

YES, python have a ternary operator, here is the syntax and an example code to demonstrate the same :)

#[On true] if [expression] else[On false]
# if the expression evaluates to true then it will pass On true otherwise On false


a= input("Enter the First Number ")
b= input("Enter the Second Number ")

print("A is Bigger") if a>b else print("B is Bigger")
  • I have added a one line statement example to check which number is big to elaborate it further – realmanusharma Oct 21 '18 at 20:45
  • 1
    `print` is really not a good choice, as this will give a SyntaxError in Python2. – Thierry Lathuille Oct 21 '18 at 21:52
  • @Thierry Lathuille here I used print() function not print statement, print function is for Python 3 while print statement is for Python 2 – realmanusharma Oct 21 '18 at 21:54
  • The question has already been asked on SO, just try it with Python 2 and you will see by yourself. 'print('hello') is a perfectly valid syntax in Python 2.7, but the way it is parsed makes your code above throw a SyntaxError. – Thierry Lathuille Oct 21 '18 at 21:58
8

Vinko Vrsalovic's answer is good enough. There is only one more thing:

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

Walrus operator in Python 3.8

After that walrus operator was introduced in Python 3.8, there is something changed.

(a := 3) if True else (b := 5)

gives a = 3 and b is not defined,

(a := 3) if False else (b := 5)

gives a is not defined and b = 5, and

c = (a := 3) if False else (b := 5)

gives c = 5, a is not defined and b = 5.

Even if this may be ugly, assignments can be done inside conditional expressions after Python 3.8. Anyway, it is still better to use normal if statement instead in this case.

David Chung
  • 47
  • 1
  • 6
5

Other answers correctly talk about the Python ternary operator. I would like to complement by mentioning a scenario for which the ternary operator is often used but for which there is a better idiom. This is the scenario of using a default value.

Suppose we want to use option_value with a default value if it is not set:

run_algorithm(option_value if option_value is not None else 10)

or, if option_value is never set to a falsy value (0, "", etc), simply

run_algorithm(option_value if option_value else 10)

However, in this case an ever better solution is simply to write

run_algorithm(option_value or 10)
user118967
  • 2,762
  • 2
  • 23
  • 37
  • 2
    A valuable complement, but I disagree: `option_value or 10` is *not* better than `option_value if option_value is not None else 10`. It is shorter, indeed, but looks weird to me and may lead to bugs. What happens if `option_value = 0`, for instance? The first snippet will run `run_algorithm(0)` because `option_value` is not `None`. The second and third snippets, however, will run `run_algorithm(10)` because `0` is a falsy. The two snippets are not equivalent, and hence one is not better than the other. And explicit is better than implicit. – ruancomelli Oct 20 '20 at 15:21
  • @ruancomelli: Good point. I've modified the answer to reflect that correction. – user118967 Oct 22 '20 at 14:04
  • 3
    As for it looking weird, I wonder if it looked weird to you because you noticed the imprecision (that it was not really equivalent). To me it sounds natural because it reminds me saying in English: "Use this or that (if the first option is unavailable)". But of course that is subjective. It is useful to know it does not look natural to everybody. – user118967 Oct 22 '20 at 14:06
  • 1
    Much better! And thanks for the explanation regarding the "or"-idiom. It looks weird to me because I tend to think of `or` as a function mapping two arguments to a boolean, so I expect it to return either `True` or `False` (this happens in many other programming languages). But "use this or that" is a nice mnemonic and will definitely help me (and hopefully others) to remember this pattern. – ruancomelli Oct 28 '20 at 19:44
3

Python has a ternary form for assignments; however there may be even a shorter form that people should be aware of.

It's very common to need to assign to a variable one value or another depending on a condition.

>>> li1 = None
>>> li2 = [1, 2, 3]
>>> 
>>> if li1:
...     a = li1
... else:
...     a = li2
...     
>>> a
[1, 2, 3]

^ This is the long form for doing such assignments.

Below is the ternary form. But this isn't most succinct way - see last example.

>>> a = li1 if li1 else li2
>>> 
>>> a
[1, 2, 3]
>>> 

With Python, you can simply use or for alternative assignments.

>>> a = li1 or li2
>>> 
>>> a
[1, 2, 3]
>>> 

The above works since li1 is None and the interp treats that as False in logic expressions. The interp then moves on and evaluates the second expression, which is not None and it's not an empty list - so it gets assigned to a.

This also works with empty lists. For instance, if you want to assign a whichever list has items.

>>> li1 = []
>>> li2 = [1, 2, 3]
>>> 
>>> a = li1 or li2
>>> 
>>> a
[1, 2, 3]
>>> 

Knowing this, you can simply such assignments whenever you encounter them. This also works with strings and other iterables. You could assign a whichever string isn't empty.

>>> s1 = ''
>>> s2 = 'hello world'
>>> 
>>> a = s1 or s2
>>> 
>>> a
'hello world'
>>> 

I always liked the C ternary syntax, but Python takes it a step further!

I understand that some may say this isn't a good stylistic choice because it relies on mechanics that aren't immediately apparent to all developers. I personally disagree with that viewpoint. Python is a syntax rich language with lots of idiomatic tricks that aren't immediately apparent to the dabler. But the more you learn and understand the mechanics of the underlying system, the more you appreciate it.

Todd
  • 2,496
  • 1
  • 10
  • 21
-1

A neat way to chain multiple operators:

f = lambda x,y: 'greater' if x > y else 'less' if y > x else 'equal'

array = [(0,0),(0,1),(1,0),(1,1)]

for a in array:
  x, y = a[0], a[1]
  print(f(x,y))

# Output is:
#   equal,
#   less,
#   greater,
#   equal

Yaakov Bressler
  • 4,437
  • 2
  • 19
  • 41
-1

I find cumbersome the default python syntax val = a if cond else b, so sometimes I do this:

iif = lambda (cond, a, b): a if cond else b
# so I can then use it like:
val = iif(cond, a, b)

Of course, it has the downside of always evaluating both sides (a and b), but the syntax it's way clearer to me

Baruc Almaguer
  • 102
  • 1
  • 1
  • 8
-3

if variable is defined and you want to check if it has value you can just a or b

def test(myvar=None):
    # shorter than: print myvar if myvar else "no Input"
    print myvar or "no Input"

test()
test([])
test(False)
test('hello')
test(['Hello'])
test(True)

will output

no Input
no Input
no Input
hello
['Hello']
True
ewwink
  • 15,852
  • 2
  • 35
  • 50
  • 1
    While useful for similar problems, this is not a ternary conditional. It works to replace `x if x else y`, but not `x if z else y`. – Perkins Oct 11 '18 at 17:13
-3
is_spacial=True if gender = "Female" else (True if age >= 65 else False)

**

it can be nested as your need. best of luck

**

That's Enam
  • 283
  • 3
  • 16