Python中'... if ... else ...'表达式的惯用法

7

如何缩短表达式:

return '%.0f' % float_var if float_var else float_var

或者

if float_var:
    return formatted_string
else:
    return None

谢谢!


2
“更短”?你的第一个例子显然是“更短”。你为什么要问哪个更短?你是在问是否有第三个神奇地更短的例子吗?由于你的问题已经显示了哪个更短,所以不清楚你需要知道什么。 - S.Lott
7
这两个例子的代码并不相同。除了显而易见的(其中一个以某种未显示的方式预先计算“formatted_string”),第二个返回None,而第一个则返回float_var,它可能是NoneFalse0.0或其他一些值……到底是谁给这些东西点赞的呢? - Peter Hansen
@Peter Hansen:好问题。我甚至无法解释这个问题,但它已经得到了赞同。我希望点赞的人能留下一些“+1...”的评论,说明这个问题有多酷。 - S.Lott
3
@Peter Hansen, @S. Lott:解释StackOverflow的问题更多是一种艺术而非科学。对于我下面的回答,我理解这个问题的意思是:“我知道两种写if-else三元条件语句的方法。有没有更短的方式?应该在什么情况下使用其中任何一种?” - John Feminella
5个回答

32

表达式<value> if <condition> else <other_value>已经相当惯用了,肯定比另一个例子更加通俗易懂,而且在<value>简单的情况下,这种写法也可能更受欢迎。这是Python中的三元操作符,所以如果你正在寻找类似于<condition> ? <value> : <other_value>的东西,那么Python中是没有这个的。

如果计算<value><other_value>需要进行几个步骤,则使用更长的if:... else:...的替代方案。


假设您使用的是2.5或更高版本。 - Gregg Lind
@Gregg:希望是这样——否则你正在使用2.4或更早版本,这意味着你的Python版本至少有6年历史! - John Feminella
看看Centos5和其他服务器发行版,John。仍然有很多2.4版本在使用,呃! - Gregg Lind

6

我会使用括号使表达更易读:

return ('%.0f' % float_var) if float_var else float_var

当我第一次看到它时,我把它读成

return '%.0f' % (float_var if float_var else float_var)

这样做有些愚蠢。我必须试一下才能确定它的工作方式。

顺便说一下,你的第一个示例与第二个示例不相等。

if float_var:
    return formatted_string
else:
    return None

这将始终返回格式化的字符串或None。如果您传递任何计算为False(False、0、0.0、""、[]等)的内容,您的第一个示例将返回未更改的内容,因此您的返回类型可以是字符串、布尔值、列表、整数、浮点数等。这可能不是您想要的,特别是当0.0是float_var的合法值时。我建议修改您的代码如下:

return ('%.0f' % float_var) if isinstance(float_var, float) else None

或者:

try:
    return "%.0f" % float_var
except TypeError:
    return None

通过将其他整数(和长整型)转换为浮点数来实现。


@Dave,大部分都不错,但是最后一个备选方案需要注意一下,因为"%.0f" % False会返回"0",这可能也不是我们想要的结果。 - Peter Hansen
@Peter - 很好的观点,我忘记了True/False自动转换为1/0。 - Dave Kirby
1
float 的类型检查总是一个警告信号。如果期望值的两个类别是数字和 None,那么检查 is not None 比检查 isinstance(foo, float) 更有意义,因为前者仍然允许操作进行鸭子类型。 - Mike Graham

2
  • It is not clear what exactly you want to do.

    1. The most literal interpretation would have it work like this

      >>> float_var = 4.5
      >>> '%.0f' % float_var if float_var else float_var
      '5' # This is a string
      >>> float_var = 0.0
      >>> '%.0f' % float_var if float_var else float_var
      0.0 # This is a float
      

      which I am almost certain you did not want.

    2. I guess you are wanting to check for None with "if float_var"? If so, you always spell it "if foo is not None", not "if foo", the former being clearer and less bug-prone.

      If that is what you intended, I suggest you revise your model. Propagating errors by repeatedly returning None is a bad thing: it is ugly and bug-prone and non-idiomatic. Use exceptions instead.

  • Shorter is not always better. Your snippets are not painfully long or unwieldly. In fact, you will want to make them a little longer if you use them to avoid a potential bug.

    • Someone may suggest abusing the short-circuiting behavior of or for this. However, this makes code harder to read and doesn't allow you to specify between None and other false values, which often leads to bugs.

1

如果你已经在使用 v if c else u,那么你已经在使用最易读和高效的三元运算符。

还有其他方法,但它们在可读性方面存在问题。


0
float_var and "%.0f" % float_vav

这不是很棒吗?


不是:
f = 0.0
x = f and "%f" % f
type(x)
<type 'float'>
f = 0.1
x = f and "%f" % f
type(x)
<type 'str'>... 如果值为0.0,则得到一个浮点数,否则得到一个字符串。
- Kevin Little
我对此有些复杂的感受。这有点厉害。据我所知,它在逻辑上等同于'%.0f' % float_var if float_var else float_var但我不会在我的代码中使用它。我认为它很难阅读。也许只是因为这个技巧在Python中不是惯用语,而且我以前从未见过。不,不,不,我永远不会这样写!但我很受印象。 - lesnik

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