如果 Python 没有三元条件运算符,是否可以使用其他语言结构来模拟一个?
31 回答
是的,它是在 2.5 版中添加的。表达式语法为:
a if condition else b
首先condition
进行评估,然后根据 的布尔值评估和返回其中一个a
或中的一个。如果计算结果为, then被计算并返回但被忽略,否则 when被计算并返回但被忽略。b
condition
condition
True
a
b
b
a
这允许短路,因为condition
仅评估 when is truea
并且b
根本不评估,但condition
仅评估 when is falseb
并且a
根本不评估。
例如:
>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'
请注意,条件是一个表达式,而不是一个语句。这意味着您不能在条件表达式pass
中使用赋值语句或其他语句:
>>> pass if False else x = 3
File "<stdin>", line 1
pass if False else x = 3
^
SyntaxError: invalid syntax
但是,您可以使用条件表达式来分配变量,如下所示:
x = a if True else b
将条件表达式视为在两个值之间切换。当您处于“一个值或另一个值”的情况时,它非常有用,但它并没有做太多其他事情。
如果需要使用语句,则必须使用普通if
语句而不是条件表达式。
请记住,一些 Pythonistas 不赞成它,原因如下:
- 参数的顺序与
condition ? a : b
许多其他语言(如C、C++、Go、Perl、Ruby、Java、JavaScript等)的经典三元运算符的顺序不同,这可能会在不熟悉 Python 的人时导致 bug。令人惊讶的”行为使用它(他们可能会颠倒参数顺序)。 - 有些人觉得它“笨拙”,因为它与正常的思维流程背道而驰(先考虑情况,然后考虑效果)。
- 风格原因。(虽然 'inline
if
'真的很有用,让你的脚本更简洁,但它确实让你的代码复杂化了)
如果您无法记住顺序,请记住,当您大声朗读时,您(几乎)说出了您的意思。例如,x = 4 if b > 8 else 9
朗读为x will be 4 if b is greater than 8 otherwise 9
.
官方文档:
对于 2.5 之前的版本,有诀窍:
[expression] and [on_true] or [on_false]
on_true
当布尔值错误时,它可能会给出错误的结果。1
尽管它确实具有从左到右评估表达式的好处,但我认为这更清楚。
<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
作为Python 增强提案 308的一部分,2006 年添加了 Python 中条件表达式的运算符。它的形式不同于普通?:
运算符,它是:
<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]
另一种(不太可靠)但更简单的方法是使用and
和or
运算符:
result = (a > b) and x or y
x
但是,如果可以,这将行不通False
。
一种可能的解决方法是制作x
和y
列表或元组,如下所示:
result = ((a > b) and [x] or [y])[0]
或者:
result = ((a > b) and (x,) or (y,))[0]
如果您正在使用字典,而不是使用三元条件,您可以利用get(key, default)
,例如:
shell = os.environ.get('SHELL', "/bin/sh")
不幸的是,
(falseValue, trueValue)[test]
解决方案没有短路行为;因此无论条件如何,都会对falseValue
和trueValue
进行评估。这可能不是最理想的甚至是错误的(即两者都trueValue
可能falseValue
是方法并具有副作用)。
一种解决方案是
(lambda: falseValue, lambda: trueValue)[test]()
(直到知道获胜者后才执行;)),但它引入了可调用对象和不可调用对象之间的不一致。此外,它并不能解决使用属性时的情况。
所以故事是这样的 - 在三个提到的解决方案之间进行选择是在具有短路功能、至少使用 Python 2.5(恕我直言,不再是问题)和不容易出现“ trueValue
-evaluates-to-false”之间进行权衡错误。
不同编程语言的三元运算符
在这里,我只是试图展示几种编程语言之间三元运算符的一些重要区别。
JavaScript中的三元运算符
var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0
Ruby中的三元运算符
a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0
Scala中的三元运算符
val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0
R编程中的三元运算符
a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0
Python中的三元运算符
a = 1 if True else 0
# 1
b = 1 if False else 0
# 0
对于 Python 2.5 和更新版本,有一个特定的语法:
[on_true] if [cond] else [on_false]
在较旧的 Python 中,没有实现三元运算符,但可以模拟它。
cond and on_true or on_false
但是,有一个潜在的问题,如果cond
评估为True
和on_true
评估为False
thenon_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 1
1
>>> x = 1
>>> print x == 0 and 0 or 1
1
对于普通的三元运算符,您会期望这个结果:
>>> x = 0
>>> print 0 if x == 0 else 1
0
>>> x = 1
>>> print 0 if x == 0 else 1
1
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 期望 else 有第三个表达式:
[expression1 if expression2 for element in iterable]
# ^-- need an else here
这引发了一个SyntaxError: invalid syntax
. 所以上面要么是一个不完整的逻辑(也许用户期望在错误条件下没有操作)或者可能打算使用 expression2 作为过滤器 - 请注意以下是合法的 Python:
[expression1 for element in iterable if expression2]
expression2
用作列表理解的过滤器,而不是三元条件运算符。
更窄情况的替代语法:
您可能会发现编写以下内容有些痛苦:
expression1 if expression1 else expression2
expression1
必须使用上述用法进行两次评估。如果它只是一个局部变量,它可以限制冗余。但是,此用例的一个常见且高性能的 Pythonic 习惯用法是使用or
的快捷方式行为:
expression1 or expression2
这在语义上是等价的。请注意,一些样式指南可能会出于清晰的原因限制这种用法 - 它确实在非常少的语法中包含了很多含义。
正如已经回答的那样,是的,Python 中有一个三元运算符:
<expression 1> if <condition> else <expression 2>
在许多情况下<expression 1>
也用作布尔评估<condition>
。然后你可以使用短路评估。
a = 0
b = 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 False
print(foo(0) if foo(0) else bar(1))
''' foo and bar are executed once
foo executed
bar executed
1
'''
# Ternary Operator expression 1 equals to True
print(foo(2) if foo(2) else bar(3))
''' foo is executed twice!
foo executed
foo executed
2
'''
# Short-circuit evaluation second equals to True
print(foo(0) or bar(1) or blubb(2))
''' blubb is not executed
foo executed
bar executed
1
'''
# Short-circuit evaluation third equals to True
print(foo(0) or bar(0) or blubb(2))
'''
foo executed
bar executed
blubb executed
2
'''
# Short-circuit evaluation all equal to False
print(foo(0) or bar(0) or blubb(0))
''' Result is 0 (from blubb(0)) because no value equals to True
foo executed
bar executed
blubb executed
0
'''
PS:当然,短路评估不是三元运算符,但通常在短路就足够的情况下使用三元。它具有更好的可读性,并且可以链接。
模拟 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 的条件表达式的替代方案之一
"yes" if boolean else "no"
如下:
{True:"yes", False:"no"}[boolean]
它具有以下不错的扩展名:
{True:"yes", False:"no", None:"maybe"}[boolean_or_none]
最短的选择仍然是:
("no", "yes")[boolean]
但别无选择
yes() if boolean else no()
如果你想避免评估yes()
and no()
,因为在
(no(), yes())[boolean] # bad
no()
和都yes()
被评估。
a if condition else b
如果您难以记住,只需记住这个金字塔:
condition
if else
a b
三元条件运算符仅允许在单行中测试条件,替换多行 if-else,从而使代码紧凑。
句法:
[on_true] 如果 [表达式] 否则 [on_false]
1- 使用三元运算符的简单方法:
# 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- 使用元组、字典和 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])
# 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 Dictionary
print((lambda: b, lambda: a)[a < b]()) # in output you should see three 10
3- 三元运算符可以写成嵌套的 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")
上述方法可以写成:
# 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
你可以这样做:
[condition] and [expression_1] or [expression_2];
例子:
print(number%2 and "odd" or "even")
如果数字是奇数,这将打印“奇数”,如果数字是偶数,则打印“偶数”。
结果:如果条件为真,则执行exp_1,否则执行exp_2。
注意: 0、None、False、emptylist 和 emptyString 的计算结果为 False。
并且除 0 以外的任何数据都评估为 True。
以下是它的工作原理:
如果条件 [condition] 变为“True”,则表达式_1 将被计算,而不是表达式_2。
如果我们用 0(零)“和”某物,结果将始终为假。所以在下面的声明中,
0 and exp
表达式exp根本不会被计算,因为带有 0 的 "and" 总是会计算为零并且不需要计算表达式。这就是编译器本身在所有语言中的工作方式。
在
1 or exp
表达式exp根本不会被计算,因为带有 1 的“或”总是 1。所以它不会费心计算表达式 exp,因为结果无论如何都会是 1(编译器优化方法)。
但万一
True and exp1 or exp2
第二个表达式 exp2 不会被计算,因为True and exp1
当 exp1 不为假时,它会为真。
同样在
False and exp1 or exp2
表达式exp1不会被计算,因为 False 相当于写 0 并且用 0 做“与”本身就是 0,但是在 exp1 之后,因为使用了“或”,它会在“或”之后计算表达式 exp2。
注意:-这种使用“or”和“and”的分支只能在 expression_1 的真值不为 False(或 0 或 None 或 emptylist [ ] 或 emptystring ' ')时使用,因为如果 expression_1 变为False,则由于 exp_1 和 exp_2 之间存在“或”,将计算 expression_2。
如果您仍然想让它适用于所有情况,而不管 exp_1 和 exp_2 真值是什么,请执行以下操作:
[condition] and ([expression_1] or 1) or [expression_2];
Vinko Vrsalovic 的回答已经足够好了。只有一件事:
请注意,条件是一个表达式,而不是一个语句。这意味着您不能在条件表达式
pass
中使用赋值语句或其他语句
Python 3.8 中的海象运算符
在Python 3.8 中引入海象运算符后,情况发生了变化。
(a := 3) if True else (b := 5)
给出a = 3
和b is not defined
,
(a := 3) if False else (b := 5)
给出a is not defined
和b = 5
, 和
c = (a := 3) if False else (b := 5)
给出c = 5
,a is not defined
和b = 5
.
即使这可能很难看,在 Python 3.8 之后的条件表达式中也可以进行赋值。无论如何,在这种情况下,最好还是使用普通语句。if
更多的是一个提示而不是一个答案(我不需要第一百次重复显而易见的事情),但我有时将它用作此类构造中的单行快捷方式:
if conditionX:
print('yes')
else:
print('nah')
,变为:
print('yes') if conditionX else print('nah')
一些(很多 :) 可能会认为它是非 Python 的(甚至是 Ruby 风格的 :),但我个人觉得它更自然 - 即,你如何正常表达它,加上在大块代码中更具视觉吸引力。
许多从C派生的编程语言通常具有以下三元条件运算符的语法:
<condition> ? <expression1> : <expression2>
起初,Python 的仁慈独裁者(当然,我是指Guido van Rossum)拒绝了它(作为非 Pythonic 风格),因为对于不习惯 C 语言的人来说,它很难理解。此外,冒号:
在 Python 中已经有很多用途。在PEP 308获得批准后,Python 终于收到了自己的快捷条件表达式(我们现在使用的):
<expression1> if <condition> else <expression2>
因此,首先它评估条件。如果返回True
,则计算表达式1 以给出结果,否则计算表达式2。由于惰性求值机制——只会执行一个表达式。
以下是一些示例(条件将从左到右评估):
pressure = 10
print('High' if pressure < 20 else 'Critical')
# Result is 'High'
三元运算符可以串联起来:
pressure = 5
print('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 有一个三元运算符,这里是语法和示例代码来演示相同的:)
#[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")
其他答案正确地谈论了 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)
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]
>>>
上面的工作是因为li1
isNone
并且解释器在逻辑表达式中将其视为 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 是一种语法丰富的语言,具有许多惯用技巧,这些技巧对于涉猎者来说并不明显。但是你越了解和了解底层系统的机制,你就越欣赏它。
Pythonic的做事方式:
"true" if var else "false"
但是也总是存在一种不同的方式来处理三元条件:
"true" and var or "false"
if else-if版本可以写成:
sample_set="train" if "Train" in full_path else ("test" if "Test" in full_path else "validation")
有多种方法。最简单的一种是使用“打印”方法中的条件。
您可以使用
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 语法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)
当然,它总是评估双方(a和b)的缺点,但语法对我来说更清晰。
链接多个运算符的巧妙方法:
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
如果定义了一个变量并且你想检查它是否有一个值,你可以使用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)
将输出
no Input
no Input
no Input
hello
['Hello']
True
is_spacial=True if gender = "Female" else (True if age >= 65 else False)
**
它可以根据您的需要嵌套。祝你好运
**