Python有三元条件运算符吗?

Python中有三元条件运算符吗?

2661915 次浏览

是的,它在2.5版中是添加。表达式语法是:

a if condition else b

首先计算condition,然后根据conditiona0值计算并返回ab中的一个。如果condition计算为True,则计算并返回a但忽略b,否则计算并返回b但忽略a

这允许短路,因为当condition为真时,只有a被评估,b根本不被评估,但当condition为假时,只有b被评估,a根本不被评估。

例如:

>>> 'true' if True else 'false''true'>>> 'true' if False else 'false''false'

请注意,条件是表达式,而不是声明。这意味着您不能在条件表达式中使用声明,例如pass,或带有=的赋值(或像+=这样的“增强”赋值):

>>> pass if False else passFile "<stdin>", line 1pass if False else pass^SyntaxError: invalid syntax
>>> # Python parses this as `x = (1 if False else y) = 2`>>> # The `(1 if False else x)` part is actually valid, but>>> # it can't be on the left-hand side of `=`.>>> x = 1 if False else y = 2File "<stdin>", line 1SyntaxError: cannot assign to conditional expression
>>> # If we parenthesize it instead...>>> (x = 1) if False else (y = 2)File "<stdin>", line 1(x = 1) if False else (y = 2)^SyntaxError: invalid syntax

(在3.8及更高版本中,:=“walrus”运算符允许简单赋值作为一种表达,然后与此语法兼容。但请不要编写这样的代码;它很快就会变得很难理解。)

同样,因为它是一个表达式,所以else部分是强制性

# Invalid syntax: we didn't specify what the value should be if the# condition isn't met. It doesn't matter if we can verify that# ahead of time.a if True

但是,您可以使用条件表达式来分配变量,如下所示:

x = a if True else b

例如,返回一个值:

# Of course we should just use the standard library `max`;# this is just for demonstration purposes.def my_max(a, b):return a if a > b else b

把条件表达式想象成两个值之间的切换。当我们处于一个值或另一个值的情况时,我们可以使用它,无论条件是否满足,我们都将结果做同样的事情。我们使用表达式来计算值,然后对其做一些事情。如果你需要根据条件做些不同的事情,那么使用普通的if声明代替。


请记住,一些Pythonistas不赞成它,原因有几个:

  • 参数的顺序与许多其他语言(例如CC++perlrubyJavajavascript等)的经典condition ? a : b三元运算符的顺序不同,当不熟悉Python“令人惊讶”行为的人使用它时,可能会导致错误(他们可能会颠倒参数顺序)。
  • 有些人认为它“笨拙”,因为它违背了正常的思维流程(首先考虑条件,然后考虑效果)。
  • (尽管内联if可能是真的有用的,并且使您的脚本更简洁,但它确实使您的代码复杂化)

如果你记不住顺序,那么请记住,当大声朗读时,你(几乎)说出了你的意思。例如,x = 4 if b > 8 else 9被大声朗读为x will be 4 if b is greater than 8 otherwise 9

官方留档:

留档

条件表达式(有时称为“三元运算符”)在所有Python操作中优先级最低。

表达式x if C else y首先计算条件C不是x);如果C为真,则计算x并返回其值;否则,计算y并返回其值。

有关条件表达式的更多详细信息,请参阅PEP 308

自2.5版以来的新功能。

对于2.5之前的版本,有一个技巧:

[expression] and [on_true] or [on_false]

on_true具有错误的布尔值时,它可能会给出错误的结果。1

虽然它确实有从左到右评估表达式的好处,在我看来这更清楚。

1.是否有相当于C的"?:"三元运算符?

您可以索引到元组:

(falseValue, trueValue)[test]

test需要返回TrueFalse
更安全的做法是:

(falseValue, trueValue)[test == True]

或者您可以使用内置的#0来确保布尔值:

(falseValue, trueValue)[bool(<expression>)]

不幸的是,该

(falseValue, trueValue)[test]

解决方案没有短路行为;因此无论条件如何,falseValuetrueValue都会被评估。这可能是次优的,甚至是错误的(即trueValuefalseValue都可能是方法并有副作用)。

解决这个问题的一个办法是

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

(延迟执行直到获胜者已知;)),但它引入了可调用和不可调用对象之间的不一致。此外,它不能解决使用属性时的情况。

因此,在三个提到的解决方案之间进行选择是在具有短路功能,至少使用Python 2.5(IMHO,不再是问题)和不容易出现“trueValue-评估为假”错误之间进行权衡。

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

a = 1b = 2
1 if a > b else -1# Output is -1
1 if a > b else -1 if a < b else 0# Output is -1

对于Python 2.5及更高版本,有一个特定的语法:

[on_true] if [cond] else [on_false]

在较旧的Python中,没有实现三元运算符,但可以模拟它。

cond and on_true or on_false

但是,存在一个潜在的问题,如果cond的计算结果为Trueon_true的计算结果为False,则返回on_false而不是on_true。如果你想要这种行为,该方法是可以的,否则使用以下命令:

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

可以通过以下方式包装:

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

并使用这种方式:

q(cond, on_true, on_false)

它与所有Python版本兼容。

你可能经常会发现

cond and on_true or on_false

但这导致了一个问题,当on_true==0

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

对于普通的三元运算符,您会期望此结果:

>>> x = 0>>> print 0 if x == 0 else 10>>> x = 1>>> print 0 if x == 0 else 11

模拟Python三元运算符。

例如

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

输出:

'b greater than a'

Python中条件表达式的运算符于2006年作为Python增强提案308的一部分添加。它的形式与常见的?:运算符不同,它是:

<expression1> if <condition> else <expression2>

这相当于:

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

下面是一个例子:

result = x if a > b else y

另一种可以使用的语法(与2.5之前的版本兼容):

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

其中操作数为懒惰地评价

另一种方法是索引元组(这与大多数其他语言的条件运算符不一致):

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

或显式构造的字典:

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

另一种(不太可靠)但更简单的方法是使用andor运算符:

result = (a > b) and x or y

但是,如果xFalse,这将不起作用。

一种可能的解决方法是制作xy列表或元组,如下所示:

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

或:

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

如果您正在使用字典,而不是使用三元条件,您可以利用#0,例如:

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

来源:?:在Python维基百科

Python有三元条件运算符吗?

是的。从语法文件

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

感兴趣的部分是:

or_test ['if' or_test 'else' test]

因此,三元条件操作的形式如下:

expression1 if expression2 else expression3

expression3将被懒惰地评估(也就是说,仅当expression2在布尔上下文中为false时才评估)。并且由于递归定义,您可以无限期地链接它们(尽管它可能被认为是糟糕的风格)。

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

关于用法的说明:

请注意,每个if后面都必须跟着一个else。学习列表理解和生成器表达式的人可能会发现这是一个很难学习的课程——以下内容将不起作用,因为Python需要第三个表达式来表示其他值:

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

这引发了一个SyntaxError: invalid syntax。所以上面是一个不完整的逻辑(也许用户期望在false条件下无操作),或者可能打算使用expression2作为过滤器-注意以下是合法的Python:

[expression1 for element in iterable if expression2]

expression2作为列表理解的过滤器,没有是三元条件运算符。

用于更窄情况的替代语法:

你可能会发现写以下内容有点痛苦:

expression1 if expression1 else expression2

expression1必须使用上述用法评估两次。如果它只是一个局部变量,它可以限制冗余。然而,这个用例的一个常见且高性能的Pythonic习惯用法是使用or的快捷行为:

expression1 or expression2

这在语义学中是等价的。请注意,一些样式指南可能会以清晰为由限制这种用法-它确实在很少的语法中包含了很多含义。

与其说是答案,不如说是提示(我不需要第一百次重复显而易见的事情),但我有时会在这样的结构中使用它作为单行快捷方式:

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

,变成:

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

有些人(许多人:)可能不赞成它是unpythonic(甚至,Ruby-ish:),但我个人认为它更自然-即,你如何正常表达它,加上在大块代码中更具视觉吸引力。

不同编程语言的三元运算符

在这里,我只是试图展示几种编程语言之间三元算子的一些重要差异。

JavaScript中的三元运算符

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

Ruby中的三元运算符

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

Scala中的三元运算符

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

R编程中的三元运算符

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

Python中的三元运算符

a = 1 if True else 0# 1b = 1 if False else 0# 0

你可以这样做:

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

示例:

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

如果数字是奇数,这将打印“奇数”,如果数字是偶数,则打印“偶数”。


结果:如果条件为真,exp_1执行,否则exp_2执行。

备注: 0、无、False、emptylist和emptyString的计算结果为False。

除0以外的任何数据都计算为True。

以下是它的工作原理:

如果条件变为“True”,则将评估expression_1,但不expression_2。

如果我们用0(零)表示“and”,结果总是假的。所以在下面的语句中,

0 and exp

表达式exp根本不会被求值,因为带有0的“and”将始终求值为零,并且不需要求值表达式。这就是编译器本身在所有语言中的工作方式。

1 or exp

表达式exp根本不会被求值,因为带1的“或”永远是1。所以计算表达式exp不会有麻烦,因为结果无论如何都是1(编译器优化方法)。

但万一

True and exp1 or exp2

第二个表达式exp2将不会被求值,因为当exp1不为假时,True and exp1将为True。

同样在

False and exp1 or exp2

表达式ex1将不会被求值,因为False等价于写0,并且用0做“and”本身就是0,但是在使用“or”之后,它将在“or”之后求值表达式ex2。


注:-这种使用“or”和“and”的分支只能在expression_1没有True值False(或0或无或emptylist[]或emptystring ' '.) 时使用,因为如果expression_1变为False,那么expression_2将被评估,因为exp_1和exp_2之间存在“or”。

如果您仍然希望使其适用于所有情况,无论exp_1和exp_2真值是什么,请执行以下操作:

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

三元条件运算符只允许在单行中测试条件,而不是多行的if-else,从而使代码紧凑。

语法:

[on_true]如果[表情]否则[on_false]

1-使用三元运算符的简单方法:

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

2-直接使用元组、字典和lambda的方法:

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

3-三元运算符可以写成嵌套的if-else:

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

上述方法可以写成:

# Python program to demonstrate nested ternary operatora, b = 10, 20if 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

,Python有一个三元运算符,这里是语法和示例代码来演示相同:)

#[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")
a if condition else b

只要记住这个金字塔,如果你有麻烦记住:

     conditionif           elsea                   b

许多从C派生的编程语言通常具有以下三元条件运算符语法:

<condition> ? <expression1> : <expression2>

起初,Python的终生仁慈的独裁者(我的意思是Guido van Rossum,当然)拒绝了它(作为非Pythonic风格),因为对于不习惯C语言的人来说很难理解。此外,冒号#0已经在Python中有很多用途。在PEP 308被批准后,Python终于获得了自己的快捷条件表达式(我们现在使用的):

<expression1> if <condition> else <expression2>

所以,首先它评估条件。如果它返回True,将评估表情1以给出结果,否则将评估表情2。由于懒评估机制-只会执行一个表达式。

以下是一些示例(条件将从左到右评估):

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

三元运算符可以串联:

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

下一个与上一个相同:

pressure = 5
if pressure < 20:if pressure < 10:print('Normal')else:print('High')else:print('Critical')
# Result is 'Normal'

Python条件表达式的替代品之一

"yes" if boolean else "no"

内容如下:

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

它有以下很好的扩展:

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

最短的选择是

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

这是因为issubclass(bool, int)

小心,虽然:替代

yes() if boolean else no()

没有

(no(), yes())[boolean]  # bad: BOTH no() and yes() are called

(no, yes)[boolean]()

只要使用完全相同的参数调用noyes,这就可以正常工作。如果它们不是,就像在

yes("ok") if boolean else no()  # (1)

或在

yes("ok") if boolean else no("sorry")  # (2)

那么类似的替代方案要么不存在(1),要么几乎不可行(2)。(在极少数情况下,取决于上下文,类似于

msg = ("sorry", "ok")[boolean](no, yes)[boolean](msg)

可能有意义)。

感谢Radek Rojík的评论

链接多个运算符的巧妙方法:

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

如前所述,是的,Python中有一个三元运算符:

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

在许多情况下,<expression 1>也用作布尔计算<condition>。然后您可以使用短路评估

a = 0b = 1
# Instead of this:x = a if a else b# Evaluates as 'a if bool(a) else b'
# You could use short-circuit evaluation:x = a or b

短路评估的一个主要优点是链接两个以上表达式的可能性:

x = a or b or c or d or e

当使用函数时,它在细节上更不同:

# Evaluating functions:def foo(x):print('foo executed')return x

def bar(y):print('bar executed')return y

def blubb(z):print('blubb executed')return z

# Ternary Operator expression 1 equals to Falseprint(foo(0) if foo(0) else bar(1))''' foo and bar are executed oncefoo executedbar executed1'''
# Ternary Operator expression 1 equals to Trueprint(foo(2) if foo(2) else bar(3))''' foo is executed twice!foo executedfoo executed2'''
# Short-circuit evaluation second equals to Trueprint(foo(0) or bar(1) or blubb(2))''' blubb is not executedfoo executedbar executed1'''
# Short-circuit evaluation third equals to Trueprint(foo(0) or bar(0) or blubb(2))'''foo executedbar executedblubb executed2'''
# Short-circuit evaluation all equal to Falseprint(foo(0) or bar(0) or blubb(0))''' Result is 0 (from blubb(0)) because no value equals to Truefoo executedbar executedblubb executed0'''

PS:当然,短路评估不是三元算子,但通常在短路足够的情况下使用三元。它具有更好的易读性并且可以链接。

Python有一个三元形式的赋值;然而,人们应该知道甚至可能有一个更短的形式。

通常需要根据条件为变量分配一个值或另一个值。

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

^这是做这样的作业的长形式。

下面是三元形式。但这不是最简洁的方式——参见最后一个例子。

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

使用Python,您可以简单地使用or进行替代赋值。

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

上面的工作原理是因为li1None,解释器在逻辑表达式中将其视为False。然后解释器继续并评估第二个表达式,它不是None,也不是空列表-因此它被分配给一个

这也适用于空列表。例如,如果您想将a分配给任何包含项目的列表。

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

了解了这一点,您可以在遇到它们时简单地进行此类赋值。这也适用于字符串和其他可迭代对象。您可以将a赋值给任何不为空的字符串。

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

我一直喜欢C三元语法,但Python更进一步!

我知道有些人可能会说这不是一个好的风格选择,因为它依赖于并非所有开发人员都能立即看到的机制。我个人不同意这种观点。Python是一种语法丰富的语言,有很多习语技巧,涉猎者并不能立即看到。但是你对底层系统的机制学习和理解得越多,你就会越欣赏它。

我发现默认的Python语法val = a if cond else b很麻烦,所以有时我会这样做:

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

当然,它有总是评估双方(一个b)的缺点,但语法对我来说更清晰。

其他答案正确地谈论了Python三元运算符。我想通过提到一个经常使用三元运算符的场景来补充,但有一个更好的习惯用法。这是使用默认值的场景。

假设我们想使用option_value,如果它没有设置默认值:

run_algorithm(option_value if option_value is not None else 10)

或者,如果option_value从未设置为假值(0""等),则只需

run_algorithm(option_value if option_value else 10)

然而,在这种情况下,一个更好的解决方案是简单地写

run_algorithm(option_value or 10)

Vinko Vrsalovic的回答就足够了。还有一件事:

请注意,条件是表达式,而不是声明。这意味着您不能在条件表达式中使用赋值语句或pass或其他声明

Python 3.8中的海象运算符

在Python 3.8中引入海象操作员之后,有些事情发生了变化。

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

给出a = 3b is not defined

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

给出a is not definedb = 5,并且

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

给出c = 5a is not definedb = 5

即使这可能很难看,任务可以在Python 3.8之后完成里面条件表达式。无论如何,在这种情况下,最好使用普通的if声明

Pythonic做事情的方式:

"true" if var else "false"

但是总是存在一种不同的方法来实现三元条件:

"true" and var or "false"

如果否则-如果版本可以写成:

sample_set="train" if "Train" in full_path else ("test" if "Test" in full_path else "validation")

有多种方法。最简单的一种是使用“print”方法中的条件。

您可以使用

print("Twenty" if number == 20 else "Not twenty")

这相当于:

if number == 20:print("Twenty")else:print("Not twenty")

这样,也可以打印两个以上的语句。例如:

if number == 20:print("Twenty")elif number < 20:print("Lesser")elif 30 > number > 20:print("Between")else:print("Greater")

可以写成:

print("Twenty" if number == 20 else "Lesser" if number < 20 else "Between" if 30 > number > 20 else "Greater")

是的,它有,但它与类似C语法的编程语言(condition ? value_if_true : value_if_false)不同

在Python中,它是这样的:value_if_true if condition else value_if_false

示例:even_or_odd = "even" if x % 2 == 0 else "odd"

Python中三元运算符的语法是:

[on_true] if [expression] else [on_false]

使用该语法,以下是我们如何使用Python的三元运算符重写上面的代码:

game_type = 'home'shirt = 'white' if game_type == 'home' else 'green'

它仍然非常清晰,但要短得多。请注意,表达式可以是任何类型的表达式,包括函数调用,它返回一个计算结果为True或False的值。