一行式条件赋值语句

206

我有以下代码

num1 = 10
someBoolValue = True

如果 someBoolValueTrue,我需要将 num1 的值设置为 20;否则不做任何操作。下面是我的代码:

num1 = 20 if someBoolValue else num1

有没有什么方法可以避免 ...else num1 这部分,使它看起来更加简洁?是否有等价的替代方案?

if someBoolValue:
    num1 = 20

我尝试用这个来替换: ...else pass ,像这样:num1=20 if someBoolValue else pass。但是我得到了语法错误。我也不能省略 ...else num1 部分。


2
将所有内容更改为num1 = 20 if someBoolValue else 10。那么您也要保存num1=10这一行吗? - Thomas Ahle
谢谢。但这并不是我的代码。我是指num1已经存在了... - bdhar
14个回答

303

我认为在Python中这是不可能的,因为你实际上尝试做的事情可能会被扩展为类似于以下的内容:

num1 = 20 if someBoolValue else num1

如果你排除了else num1,你将会收到语法错误,因为我非常确定赋值必须返回某些内容。

正如其他人已经提到的,你可以这样做,但这是不好的,因为下次阅读这段代码时可能只会让你更加困惑:

if someBoolValue: num1=20

我不是太喜欢num1 = someBoolValue and 20 or num1这一行代码,因为我需要思考一下它的实际含义。

要实现你想做的事情,最好还是使用原始版本:

if someBoolValue:
    num1 = 20
那个版本是最好的原因是因为它非常明显你想要做什么,而且你不会混淆自己或者后来接触那段代码的人。
另外,顺带一提,num1 = 20 if someBoolValue 是有效的 Ruby 代码,因为 Ruby 的工作方式有些不同。

18
根据PEP-308规范 (https://docs.python.org/2.5/whatsnew/pep-308.html),如果将条件表达式放在括号中,可以使其更加清晰,例如`num1 = (20 if someBoolValue else num1)`。 - haridsv
1
要注意除以零的语句--即使条件为假,如果my_var为0,则num_cats = math.ceil(num_humans / my_var) if my_var > 1 else 1会生成除以零。 - bunkerdive

68

使用这个:

num1 = 20 if someBoolValue else num1

6
这是我一直在使用的东西,现在正在寻找替代品。无论如何,还是谢谢! - bdhar
如何调用这个代码块?我的意思是它的名称是什么? - fuat
4
它是一个三目运算符。 - Chris Maes
2
如果循环遍历大数据集,则不应使用此方法,因为如果我们最终进入else语句,则会引入不必要的赋值。 - dapc

38

对于来自Google的未来时空旅行者,这里有一种新的方法(从Python 3.8开始可用):

b = 1
if a := b:
    # this section is only reached if b is not 0 or false.
    # Also, a is set to b
    print(a, b)

这被称为“海象运算符”。更多信息请参见Python 3.8的新功能页面。

1
请注意,此功能仅适用于Python>=3.8版本。 - Amer Sawan
新的if-else代码风格的最佳澄清。谢谢。 - F.Tamy
1
能够像这样立即在条件中使用 a 就太好了:if a := b and a != 0 - Gleb Ignatev
2
请问您能否将变量num1和someBoolValue适配到问题中吗? - PythoNic
1
@PythoNic他们不能,因为答案与问题无关。 - undefined
显示剩余2条评论

26
在一行中:
if someBoolValue: num1 = 20

但不要这样做。通常不建议使用这种风格,人们更喜欢使用更长的形式以便于理解和保持一致性。

if someBoolValue:
    num1 = 20
同样地,应避免使用骆驼命名法。因此,最好使用 some_bool_value
请注意,没有一个不带else部分的内联表达式 some_value if predicate,因为如果谓词为假,则不会有返回值。但是,在所有情况下,表达式必须具有明确定义的返回值。这与在Ruby或Perl中的用法不同。

2
因为代码难以阅读,而且你很可能会被自己的代码搞糊涂,这绝不是明智之举。 - Frost
1
@bdhar,你为什么想把它放在一行上?这样做不会使程序运行更快,只会让其他人阅读更困难。 - John La Rooy
1
@gnibbler,其实没有什么特别的原因。我只是在寻找一个更短、更易读的形式。 - bdhar

19

你可以使用以下其中之一:

(falseVal, trueVal)[TEST]

TEST and trueVal or falseVal

1
漂亮的一行代码条件赋值 - minhas23
那个“结构”叫什么?我在学习Python的六个月中从未见过它。 - Guimoute
2
至少这些不是作业,除非你把它们放在前面,第二,它们不会按照描述的方式工作。第一个创建了一个元组,然后通过索引选择其中一个元素。它只适用于返回介于-1和1之间的整数或True/False的测试,因为boolint的子类。在所有情况下,如果测试返回某些只会评估为真的结果,则会失败并引发异常。第二个仅在trueVal本身不会评估为假的情况下才起作用,否则即使测试为真,也将分配falseVal - Bachsau
它非常简洁,但要作为“推荐模式”安全使用也非常棘手,参见Bachsau的评论...(因此我对其进行了投票否决) - tverrbjelke

17
如果你一定会写出单行代码,Python 3.8 引入了被亲切地称为“海象运算符”的赋值表达式

:=

someBoolValue and (num := 20)

如果第一个布尔表达式为True,则20将被分配给num。此处赋值必须在括号内,否则会出现语法错误。
num = 10
someBoolValue = True

someBoolValue and (num := 20)
print(num) # 20

num = 10
someBoolValue = False

someBoolValue and (num := 20)
print(num) # 10

6
不行。我猜你希望类似于 num1 = 20 if someBoolValue 这样的东西可以工作,但它不能。我认为最好的方法是使用你已经写好的 if 语句:
if someBoolValue:
    num1 = 20

6
num1 = 10 + 10*(someBoolValue is True)

这是我的最终答案。 之前的答案过于复杂,对于所述问题来说有点过度设计。变得太聪明 == 不好。以下是之前的答案... 如果你想为True条件添加一件事情,而为False添加另一件事情,则仍然可以使用:

num1 = 10 + (0,10)[someBoolValue is True]

你提到num1已经有一个值,应该不需要改变。我假设num1 = 10,因为这是帖子的第一条语句,所以得到20的操作是加上10

num1 = 10
someBoolValue = True

num1 = 10 + (0,10)[someBoolValue is True]

print(f'num1 = {num1}\nsomeBoolValue = {someBoolValue}')

生成此输出

num1 = 20
someBoolValue = True

现在我在考虑,我应该回答'num1 = 10 + 10*(someBoolValue == True)'。问题定义为'False'条件基本上是一个无操作。如果需要为'False'添加不同的值,则先前的答案更适合。我应该编辑我的帖子还是在评论中进行? - Mike from PSG

3
num1 = 20 * someBoolValue or num1

3

如果你希望在某个布尔值为真时调用一个方法,你可以加上else None来终止三元运算符。

>>> a=1
>>> print(a) if a==1 else None
1
>>> print(a) if a==2 else None
>>> a=2
>>> print(a) if a==2 else None
2
>>> print(a) if a==1 else None
>>>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接