如何在Python lambdas中表达条件执行?

时间:2011-02-28 13:12:18

标签: python lambda conditional short-circuiting inline-if

我发现了什么:

深入Python 中,我读到了andor运算符的特殊性质 以及如何使用布尔运算符的短路评估来更简洁地表达条件,and-or trick非常类似于C中的三元运算符。

C:

result = condition ? a : b

的Python:

result = condition and a or b

这似乎派上用场了,因为lambda函数仅限于Python中的单行,但它使用逻辑语法来表达控制流。

从Python 2.5开始,内联 - if似乎已经成为了一种更具可读性的语法和技巧:

result = a if condition else b

所以我猜这是对可读性较差的构造的pythonic替代品。 即使我想要嵌套多个条件,它仍然看起来非常全面:

result = a if condition1 else b if condition2 else c

但在一个不确定的世界里,我经常发现自己编写了一些这样的代码来访问a.b.c:

result = a and hasattr(a, 'b') and hasattr(a.b, 'c') and a.b.c or None 

所以在 inline-if 的帮助下,我可以摆脱一些 ands ors ,从而产生一个非常易读的部分代码:

result = a.b.c if hasattr(a, 'b') and hasattr(a.b, 'c') else None

我还在这个recipe

中发现了一种对于conditonals有些神秘的方法
result = (a, b)[condition] 

但是这不会短路,如果条件的结果没有返回布尔值,则会导致各种错误,0或1。

我想知道的是:

现在我想知道,如果向下兼容性不是一个问题,那么尽可能使用内联 - if是否被认为是更好/更pythonic,或者只是一个品味问题和一个人的感受在短路评估领域的家乡?

更新

我刚刚意识到inline-if不仅仅是for-or-trick的语法糖,因为当布尔上下文中a为false时它不会失败。所以它可能更加防止失败。

4 个答案:

答案 0 :(得分:2)

由于存在一个特殊的语言构造,其中内联if - else可以执行您想要的内容以及引入的内容来替换您提到的丑陋的变通方法,因此使用它是个好主意它。特别是因为and - or技巧之类的黑客通常会出现意想不到的极端情况/错误。

例如and - or技巧在这种情况下失败:

a = 0
b = 1
c = True and a or b

c将是1,如果您正在寻找if - else语义,那么这不是您所期望的。

那么,当有一种语言结构可以完全符合您的要求时,为什么要使用错误的变通方法呢?

答案 1 :(得分:2)

pythonic要做的就是识别当你将代码拉伸到一个合理的东西时,只需要使用一个普通的函数。请记住,使用命名函数无法对lambda执行任何操作。

当然,每个人的突破点都不同,但如果你发现自己在写作:

return a.b.c if hasattr(a, 'b') and hasattr(a.b, 'c') else None

过多,请考虑改为:

try:
     return a.b.c
except AttributeError:
     return None

答案 2 :(得分:0)

我宁愿明确我的代码在做什么。内联if非常明确地进行条件赋值和可读性确实很重要。如果和/或副作用被认为是优选的话,内联是否会使其成为语言。

条件表达式的pep更详细地介绍了为什么选择了特定语法,并且它具体讨论了和/或黑客:

http://www.python.org/dev/peps/pep-0308/

答案 3 :(得分:0)

这是针对您提到的特殊情况,但我认为大多数情况下您需要链式短路逻辑都可以通过更优雅的解决方案来处理。这显然是一个品味的问题,让我补充说,如果你认为上面的内容比这更好,那就刮掉了:

try:
    foo = a.b.c

except AttributeError:
    print "woops"

在其他不那么简单的情况下,将所有测试封装在函数中可能会大大提高可读性。

编辑:顺便说一句,duck typing

相关问题