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

5 投票
4 回答
4990 浏览
提问于 2025-04-16 12:40

我发现的事情:

在《深入Python》这本书里,我读到了 andor 操作符的一些特别之处,以及布尔操作符的短路求值是如何让条件表达得更简洁的。这种方法被称为and-or技巧,它的工作方式和C语言中的三元操作符很像。

C语言示例:

result = condition ? a : b

Python示例:

result = condition and a or b

这在Python中很有用,因为lambda函数只能写成一行,但它使用逻辑语法来表达控制流。

自从Python 2.5以来,内联if似乎成为了更易读的语法,用来替代and-or技巧:

result = a if condition else b

所以我想这就是Python中更易读的替代方案,虽然我想嵌套多个条件,但看起来依然很清晰:

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 

所以借助内联if,我可能可以省去一些andor,让代码变得更易读:

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

我还发现了一种有点复杂的条件写法,在这个示例中。

result = (a, b)[condition] 

但这种方法不会短路,如果条件的结果不是布尔值、0或1,就会导致各种错误。

我想知道的事情:

现在我想知道,如果不考虑向下兼容性,使用内联if是否更受欢迎/更符合Python的风格,还是说这只是个人口味的问题,以及一个人对短路求值的熟悉程度?

更新

我刚意识到,内联if不仅仅是and-or技巧的语法糖,因为当a在布尔上下文中为假时,它不会失败。所以它可能更可靠。

4 个回答

0

这是针对你提到的特定情况,不过我觉得大多数需要链式短路逻辑的情况都可以用更优雅的解决方案来处理。这个当然是个人喜好的问题,如果你觉得上面的方式比这个更好,那就忽略我说的吧:

try:
    foo = a.b.c

except AttributeError:
    print "woops"

在其他一些不那么简单的情况下,把所有的测试放在一个函数里可能会让代码更容易阅读。

补充一下,顺便提一下鸭子类型

2

因为有一种特殊的语言结构,就是内联的 if-else,它可以实现你想要的功能,而且是为了替代那些看起来很丑陋的变通方法而引入的,所以使用它是个好主意。特别是因为像 and-or 这种技巧通常会有一些意想不到的边缘情况或者错误。

比如说,and-or 这种技巧在某些情况下会出问题:

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

在这种情况下,c 的值会变成 1,这并不是你期待的结果,如果你是想要 if-else 的效果的话。

那么,既然有一种语言结构可以完美实现你的需求,为什么还要使用那些有缺陷的变通方法呢?

2

在写代码的时候,聪明的做法是要意识到什么时候你的代码已经被挤压得太紧,放不下更多的东西了。这时候就应该用普通的函数来处理。记住,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

撰写回答