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

Seb*_*ach 6 python boolean-logic coding-style conditional-operator language-lawyer

情况

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

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

default_list = ...
custom_list = ...
if custom_list:
    list = custom_list
else:
    list = default_list
Run Code Online (Sandbox Code Playgroud)

你可以缩短到:

default_list = ...
custom_list = ...
list = custom_list if custom_list else default_list
Run Code Online (Sandbox Code Playgroud)

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

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

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

list = custom_list or default_list
Run Code Online (Sandbox Code Playgroud)

这与C#Null Coalescing运算符类似,不同之处在于它应该作为False Coalescing Operator在Python中重新生成,它返回第一个非false参数.

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

无论PEP8(程序),也不pylint的不抱怨.

the*_*eye 5

这是完全有效的,您可以使用它。甚至 的文档也or有相同的示例。

请注意,无论是和NOR或限制值并键入他们返回FalseTrue,而是返回最后一个变量。这有时很有用,例如,如果s是一个字符串,如果它是空的,则应由默认值替换,则表达式会s or 'foo'产生所需的值。

但是,该or方法具有局限性。如果你想故意允许非Truthy值,那么它是没有可能这一点。

假设您想允许一个空列表

my_list = [] or default_list
Run Code Online (Sandbox Code Playgroud)

总会给default_list。例如,

print [] or [1, 2, 3]
# [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

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

custom_list if isinstance(custom_list, list) else default_list
Run Code Online (Sandbox Code Playgroud)

清除旧文件,引用BDFL 的常见问题解答

4.16. 问:是否有等效于 C 的“?:”三元运算符?

A. 不是直接的。在很多情况下,你可以模仿a?b:ca and b or c,但有一个缺陷:如果b是零(或空,或者None-任何测试失败),则C将被替代选择。在许多情况下,您可以通过查看代码证明这不会发生(例如,因为 b 是一个常量或具有永远不会为假的类型),但通常这可能是一个问题。

Steve Majewski(或者是 Tim Peters?)提出了以下解决方案:(a and [b] or [c])[0]. 因为[b]是单例列表,它永远不会出错,所以永远不会走错路;然后应用[0]到整个事情会得到你真正想要的 b 或 c。丑陋,但它让你在极少数情况下使用'if'重写你的代码真的很不方便。


Mar*_*ers 5

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

它曾经是,现在仍然是,完美的 Pythonic 使用:

foo = bar or baz
Run Code Online (Sandbox Code Playgroud)

如果bar为 false-y则回退到默认值(在布尔上下文中计算为 false)。它短路的事实还可以让您执行以下操作:

foo = bar or expensive_calculation(baz)  # only if bar is false-y
Run Code Online (Sandbox Code Playgroud)

并且没有expensive_calculation()execute if baris truth-y(在布尔上下文中评估为真)。同样,您可以使用and来确保满足前提条件:

foo = bar and bar(baz)  # call `bar()` only if it is truth-y
Run Code Online (Sandbox Code Playgroud)

应该使用条件表达式:

foo = bar and spam or eggs
Run Code Online (Sandbox Code Playgroud)

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

foo = spam if bar else eggs
Run Code Online (Sandbox Code Playgroud)

总是选择spamifbar是真的。