是否有一个条件运算符?

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

转载于:https://stackoverflow.com/questions/394809/does-python-have-a-ternary-conditional-operator

csdnceshi76
斗士狗 Although an answer has long been accepted, I encourage the questioner (or whoever knows what the question was referring to) to rephrase 'other language constructs'. It's unclear whether you're talking about other Python constructs or constructs from other languages (although I don't know why you'd ask that).
一年多之前 回复
csdnceshi80
胖鸭 In the years since nobar's comment the conditional expression documentation has been updated to say Conditional expressions (sometimes called a “ternary operator”)...
一年多之前 回复
csdnceshi78
程序go It is mentioned here docs.python.org/3/faq/…, but not mentioned in Python Standard Library
接近 2 年之前 回复
weixin_41568127
?yb? A million duplicate answers here, but I'd just like to caution against the overuse of the ternary. One is fine, but multiple rows of ternaries can get really hard to read.
2 年多之前 回复
weixin_41568126
乱世@小熊 Wikipedia covers this thoroughly in the article "?:".
3 年多之前 回复
csdnceshi64
游.程 also ISO/IEC 9899 (the C programming language standard) section 6.5.15 calls it the "the condtitional operator"
大约 5 年之前 回复
csdnceshi64
游.程 "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.
大约 5 年之前 回复
csdnceshi55
~Onlooker 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 is somewhat more helpful and includes a link to "PEP 308", which includes a lot of interesting historical context related to this question.
大约 7 年之前 回复
weixin_41568131
10.24 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' . Wikipedia is also quite helpful Ж:-)
8 年多之前 回复

14个回答

Yes, it was added in version 2.5.
The syntax is:

a if condition else b

First condition is evaluated, then either a or b is returned based on the Boolean value of condition
If condition evaluates to True a is returned, else b is returned.

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 assignments or pass or other statements in a conditional:

>>> pass if False else x = 3
  File "<stdin>", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

In such a case, you have to use a normal if statement instead of a conditional.


Keep in mind that it's frowned upon by some Pythonistas for several reasons:

  • The order of the arguments is different from many other languages (such as C, Ruby, Java, etc.), which may lead to bugs when people unfamiliar with Python's "surprising" behaviour use it (they may reverse the 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.

If you're having trouble remembering the order, then remember that if you read it out loud, 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:

csdnceshi54
hurriedly% You might want to realize that this returns a value: e.g. name="Sally" if gender=="female" else: "John". So, something is assigned to name. A print statement doesn't return anything in Python 2.x; in Python 3.x it returns None.
一年多之前 回复
csdnceshi59
ℙℕℤℝ 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
一年多之前 回复
csdnceshi71
Memor.の That's well and good, but we're programmers, not, in the main, mathematicians. Face it, it was a boneheaded decision.
一年多之前 回复
weixin_41568196
撒拉嘿哟木头 wouldnt it be better to use it as : (false_result, truth_result)[ condition ]
接近 2 年之前 回复
csdnceshi79
python小菜 a if b if c if d else e else f if x if y else z else b if x else y ...
大约 2 年之前 回复
csdnceshi52
妄徒之命 Compared to Ruby's true if true and true unless true this isn't that confusing. It's kind of silly to force styles in Python because other languages do it differently (admittedly, it might make sense for a certain company or team, which is what style guides are for). If Python were exactly the same as C++, there would be no point in having Python.
大约 2 年之前 回复
csdnceshi50
三生石@ Irawan Agreed that the python ternary operator is confusing when overused/used inappropriately. And it can be nested to create obfuscated one-liners. But we seem to agree that there's at least one case where it's pretty natural, so it seems like problems can be avoided if we only use it in these specific scenarios where it's natural.
2 年多之前 回复
weixin_41568174
from.. I'm pretty sure that's non-intuitive. Imagine in the real world when someone says: "Go left... if you're male. But otherwise go right." Compared to: "If you're male, then go left. Otherwise, go right." The only scenarios where I think the Python ternary can be "natural" is for the exact scenario you mentioned, i.e. the check is an "OK check" and the "else" is a throw Exception. But ternary can be used for many other things, math checks, even nested, then this syntax gets really confusing.
2 年多之前 回复
csdnceshi50
三生石@ Irawan we can construct a natural language phrasing for this that's both precise & intuitive though: Do thing X as long as the normal check comes up OK; if it's not coming up OK, then go to the backup plan & do thing Y
2 年多之前 回复
weixin_41568174
from.. perhaps you mean: do A in most case, except when not B then you should do C instead (reflecting both ordering and intent of the construct). Now you realize how so not intuitive this gets.
2 年多之前 回复
csdnceshi63
elliott.david I see what you mean, so you would basically be nesting the operations: "foo" if Bool else ("bar" if Bool else "foobar")
2 年多之前 回复
csdnceshi65
larry*wei I meant something like if (c1) a1 elif (c2) a2 elif ... else a(n).
2 年多之前 回复
csdnceshi63
elliott.david you could group the boolean expressions. "foo" if (bool or bool && bool or etc) else "bar"
2 年多之前 回复
csdnceshi65
larry*wei what if there are multiple conditions ?
2 年多之前 回复
csdnceshi69
YaoRaoLov I love the vague irony of this syntactic ordering being described as natural by someone called @yota.
大约 3 年之前 回复
csdnceshi64
游.程 Really? I get "dog", not foo("dog"). foo("cat") if False else foo("dog") works for me. As does foo("cat") if False else bar("dog")
3 年多之前 回复
weixin_41568110
七度&光 try print("OK" if status else "NOT OK")
3 年多之前 回复
csdnceshi67
bug^君 If using this in the construction of strings then beware 'a' + 'b' if x else 'c' will give either 'ab' or 'c', never 'ac' so bracket accordingly.
3 年多之前 回复
weixin_41568131
10.24 That fails in Python 2 without from __future__ import print_function because print is a statement, not a function.
接近 4 年之前 回复
weixin_41568126
乱世@小熊 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)
接近 4 年之前 回复
weixin_41568126
乱世@小熊 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.
接近 4 年之前 回复
csdnceshi74
7*4 All's fine and dandy but aligning this guy can be tough. Compare to condition\n\t? expression1\n\t: expression2.
接近 4 年之前 回复
csdnceshi61
derek5. I keep getting an invalid syntax error. If my variable is populated, then it should return true, and thus perform the statement. print("OK") if status else print("NOT OK") fails at the if.
接近 4 年之前 回复
csdnceshi76
斗士狗 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...
大约 4 年之前 回复

expression1 if condition else expression2

>>> a = 1
>>> b = 2
>>> 1 if a > b else -1 
-1
>>> 1 if a > b else -1 if a < b else 0
-1
weixin_41568196
撒拉嘿哟木头 Somehow, I'm able to understand this better than the top answer.
接近 2 年之前 回复
csdnceshi65
larry*wei , 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.
大约 5 年之前 回复
csdnceshi78
程序go 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.
9 年多之前 回复
csdnceshi80
胖鸭 What's the difference between this and the top answer?
9 年多之前 回复

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?

csdnceshi63
elliott.david Here's the disassembled code. Using the method ThomasH suggested would be even slower.
接近 2 年之前 回复
csdnceshi72
谁还没个明天 Do you have source for me?
5 年多之前 回复
csdnceshi74
7*4 Ternary operator usually executes faster(sometimes by 10-25%).
大约 6 年之前 回复
csdnceshi52
妄徒之命 The remedy is to use (test and [true_value] or [false_value])[0], which avoids this trap.
10 年多之前 回复

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.

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>)]
csdnceshi75
衫裤跑路 This trick may help avoid timing based attacks on algorithms if it always evaluates both possible results and avoids skipping code (an 'if' skips).
大约 2 年之前 回复
csdnceshi64
游.程 Don't do comparisons to booleans with ==. Instead, you should always use is.
接近 3 年之前 回复
csdnceshi51
旧行李 comparisons to singletons should always use is/is not instead of ==
接近 4 年之前 回复
weixin_41568196
撒拉嘿哟木头 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.
接近 4 年之前 回复
csdnceshi76
斗士狗 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<alpha],pval).
接近 4 年之前 回复
csdnceshi57
perhaps? Is this idiomatic in python? Seems confusing but maybe its convention
4 年多之前 回复
weixin_41568126
乱世@小熊 This is great for code-golf, not so much for actual code. Although I have gotten so used to it that I do use it sometimes for conciseness when doing something obvious like picking between two string constants.
大约 5 年之前 回复
csdnceshi70
笑故挽风 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(<expression>)]. The bool() function has been around since v2.2.1.
7 年多之前 回复
weixin_41568183
零零乙 (lambda: print("a"), lambda: print("b"))[test==true]()
接近 8 年之前 回复
weixin_41568131
10.24 Note that this one always evaluates everything, whereas the if/else construct only evaluates the winning expression.
大约 9 年之前 回复

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

Now you can see the beauty of python language. its highly readable and maintainable.

csdnceshi61
derek5. 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.
一年多之前 回复
weixin_41568126
乱世@小熊 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.
大约 2 年之前 回复
csdnceshi62
csdnceshi62 "Now you can see the beauty of python language. its highly readable and maintainable." I don't see the relevance of this sentence, nor how the ternary operator syntax demonstrates it.
大约 2 年之前 回复
csdnceshi68
local-host Ruby works also with a = true ? 1 : 0
接近 3 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 This blogger found python's ternary operator to be unnecessarily different than most other languages.
大约 3 年之前 回复

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.

csdnceshi64
游.程 Wow, that looks really hacky! :) Technically, you can even write [on_false, on_True][cond is True] so the expression becomes shorter.
接近 6 年之前 回复
csdnceshi77
狐狸.fox 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.
6 年多之前 回复
csdnceshi71
Memor.の 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.
7 年多之前 回复

Absolutely, and it is incredibly easy to understand.

general syntax : first_expression if bool_expression_is_true else second_expression

Example: x= 3 if 3 > 2 else 4 
# assigns 3 to x if the boolean expression evaluates to true or 4 if it is false
csdnceshi66
必承其重 | 欲带皇冠 Just not easy to actually use if your project limits line width. :(
3 年多之前 回复

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] ;

csdnceshi53
Lotus@ 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.
2 年多之前 回复

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.

csdnceshi55
~Onlooker 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!!
3 年多之前 回复
csdnceshi80
胖鸭 expression1 or expression2 being similar and with the same drawbacks/positives as expression1 || expression2 in javascript
接近 4 年之前 回复
共14条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问