是'或'在赋值pythonic的右侧使用?

时间:2014-05-01 07:07:27

标签: python coding-style language-lawyer boolean-logic conditional-operator

情况

(注意:以下情况只是示例性的。这个问题适用于任何可以评估为bool的事情)

如果用户未提供自定义列表,则应使用默认列表:

default_list = ...
custom_list = ...
if custom_list:
    list = custom_list
else:
    list = default_list

您可以将其缩短为:

default_list = ...
custom_list = ...
list = custom_list if custom_list else default_list

现在,根据https://docs.python.org/2.7/reference/expressions.html#or ...

  

表达式x or y首先评估x;如果 x true ,则返回其值;否则,将评估 y 并返回结果值。

...,or不返回布尔值,而是返回布尔转换不为false的第一个值。因此,以下是有效的代码:

list = custom_list or default_list

这类似于C#Null Coalescing Operator,除了它应该在Python中作为 False Coalescing Operator 重新定义,它返回第一个非假的参数。

问题

最后一个例子似乎更容易阅读,但是它被认为是pythonic吗?

pep8 (程序)和 pylint 都不会抱怨。

2 个答案:

答案 0 :(得分:4)

这完全有效,你可以使用它。即使documentation of or也有相同的例子。

  

请注意,它们既不返回也不限制它们返回FalseTrue的值和类型,而是返回最后一个已计算的参数。 这有时很有用,例如,如果s是一个字符串,如果它是空的,则应该用默认值替换,表达式s or 'foo'会产生所需的值。

但是,or方法有局限性。如果你想故意允许一个非Truthy值,那么它 就不可能。

我们假设您要允许空列表

my_list = [] or default_list

将始终提供default_list。例如,

print [] or [1, 2, 3]
# [1, 2, 3]

但是使用条件表达式我们可以像这样处理它

custom_list if isinstance(custom_list, list) else default_list

删除旧文档,引用BDFL's FAQ

  

4.16。问:是否有相当于C的“?:”三元运算符?

     

一个。不是直接的。在许多情况下,您可以使用a?b:c模仿a and b or c,但有一个缺陷:如果b为零(或空,或None - 任何内容   测试错误)然后将选择c。在很多情况下你   可以通过查看代码来证明这不可能发生(例如因为   b是常数或具有永远不会是假的类型,但总的来说   这可能是个问题。

     Steve Majewski(或蒂姆·彼得斯?)建议如下   解决方案:(a and [b] or [c])[0]。因为[b]是一个单例列表   永远不会是假的,所以永远不会采取错误的道路;然后将[0]应用于   整个事情得到你真正想要的b或c。丑,但它   在极少数情况下让你到达那里真的很不方便   使用'if'重写代码。

答案 1 :(得分:4)

是的,在将条件表达式构造添加到语言之前,使用or使其短路属性成为常态

使用时,现在仍然是完全pythonic:

foo = bar or baz
如果bar为false-y(在布尔上下文中计算结果为false),则

回退到默认值。短路这一事实也可以让你做到这样的事情:

foo = bar or expensive_calculation(baz)  # only if bar is false-y

如果expensive_calculation()是true-y(在布尔上下文中求值为true),则不执行bar。同样,您可以使用and来确保满足前提条件:

foo = bar and bar(baz)  # call `bar()` only if it is truth-y

使用条件表达式:

foo = bar and spam or eggs

但是。这是条件表达式旨在取代的内容。我的想法是,如果bar是真实的,则选择spam,否则选择eggs。但如果spam是假的,那就会崩溃!这是一个常见的错误来源,而

foo = spam if bar else eggs
如果spam是真实的,

总是选择bar