False或None vs. None或False

87
In [20]: print None or False
-------> print(None or False)
False

In [21]: print False or None
-------> print(False or None)
None

这种行为让我感到困惑。有人能解释一下为什么会这样发生吗?我本以为它们会表现得一样。


2
为什么Python中没有&&和||运算符,而是and和or?还有其他类似的问题。 - S.Lott
2
可能是["布尔"操作在Python中(即:and/or运算符)]的重复问题(https://dev59.com/D2865IYBdhLWcg3wat6l)。 - S.Lott
@SilentGhost:如果None被认为与False相同,为什么它返回None而不是False?如果应用于两个false值的OR运算符不应该返回False吗? - Virgiliu
2
@SilentGhost:我看了,但是我没有理解,所以才问。 - Virgiliu
2
@SilentGhost 这很令人困惑,因为官方文档描述的与逻辑 OR 运算符直觉上期望的不同(即操作数的顺序无关紧要)。按照文档所述的行为并不一定意味着是“正确”的行为...;-) - Rolf Bartstra
6个回答

122

x or y 表达式的值取决于 x 的真假,如果 x 为真,则结果为 x,否则为 y

需要注意的是上述句子中的 "true" 和 "false" 是指 "truthiness",并不是固定值 TrueFalse。一个 "true" 值会使得 if 语句执行成功;而一个 "false" 值则会导致失败。"false" 值包括 FalseNone0[](空列表)。


6
LOL,最近被创造出来的词汇“真实感”的巧妙运用,尽管其可疑的起源不容忽视,但在这里还是相当合适的。 - martineau
7
“@martineau: 在技术上,这个词已经使用很久了。Colbert比程序员更有可能让它变得流行,但他不是唯一的来源。” - Roger Pate
2
是的,这个词显然是一个更古老的术语。在维基词典上,它们指出“首次见于1824年”。我从未看到过RichieHindle所说的技术意义——尽管在这种情况下它完全有道理。 - martineau
2
如果“false”值包括False、None、0和[](一个空列表),那么为什么None != False的结果是True - Reloader
16
@Reloader:仅仅因为两个值都是“falsey”并不意味着它们相等。 - RichieHindle
1
@Reloader:设置 truthiness = bool,然后 truthiness(None) == truthiness(False)True - martineau

18
or 运算符返回它的第一个操作数的值,如果在 Python 布尔意义上(也称为其“真实性”)为 true,则返回该值;否则返回其第二个操作数的值,无论它是什么。请参阅 当前在线文档 中关于 表达式 的子部分 布尔运算
在两个示例中,第一个操作数都被视为 false,因此第二个操作数的值成为表达式求值的结果。

14

解释

你必须意识到在Python中,TrueFalseNone都是单例对象,这意味着存在且只能存在一个单例对象的实例,因此称为单例。此外,您不能修改单例对象,因为它的状态已经确定,如果我可以使用那个短语的话。

现在,让我解释一下这些Python单例对象的使用方式。

假设有一个名为foo的Python对象,它具有值None,那么if foo is not None表示foo具有非None的值。这与说if foo相同,基本上是if foo == True

因此,not NoneTrue的作用方式相同,NoneFalse也是如此。

>>> foo = not None
>>> bool(foo)
True
>>> foo = 5  # Giving an arbitrary value here
>>> bool(foo)
True

>>> foo = None
>>> bool(foo)
False
>>> foo = 5  # Giving an arbitrary value here
>>> bool(foo)
True
在编码时,需要注意的关键是,当比较两个对象时,None 需要使用 is,而 TrueFalse 需要使用 ==。避免使用 if foo == None,只使用 if foo is None。此外,避免使用 if foo != None,只使用 if foo is not None

警告

如果在条件语句中检查变量值是否为 None 时使用 if fooif not foo,则可能会导致代码中的潜在错误。因此,不要以这种方式检查潜在的 None 值。通过上述方法检查它,即 if foo is Noneif foo is not None,这非常重要。一定要遵循 Python 专家共享的最佳实践。

提醒

True1False0
在 Python 的早期版本中,我们只有整数 1 表示真值(truthy value),并且我们有整数 0 表示假值(falsy value)。然而,使用 True 代替 1 更易于理解和人性化,使用 False 代替 0 更易于理解和人性化。

值得知道

bool 类型(即 TrueFalse)是 int 类型的子类型。因此,如果使用类型提示,并注释函数/方法返回一个 intbool (即 -> int | bool-> Union[int, bool]),那么 mypy(或任何其他静态类型检查器)将无法正确确定此类函数/方法的返回类型。这是需要注意的事情。这方面没有解决办法。

1
if foo不是None的情况下,只需执行if foo:请注意,if foo并不等同于检查Noneif语句首先将其表达式转换为bool,因此如果foo == 0,则if foo将失败。 - Norrius
在逻辑上,None、False和0是相同的东西。编码时要坚持相同的逻辑。如果你给一个变量赋予了None作为起始值,在源代码中稍后检查这个值时要坚持使用“if foo is None”,但这基本上与检查“if not foo”是相同的。这是多功能的,所以使用任何你感觉最好的方式。 - Boštjan Mejak
2
我只是想指出,“基本相同”可能是微妙错误的源头。假设你有 def fun(foo: str = None): if foo: bar。现在,如果有人传入一个空字符串会发生什么?如果在你的逻辑中,空字符串与None不同,则可能不是期望的结果。 - Norrius
当有人传入一个空字符串时,会返回None(因为所有Python函数都隐式地返回None)。 - Boštjan Mejak
1
我已经修正了我的回答。我警告在执行 if fooif not foo 时可能会出现潜在的错误。使用 if foo is not Noneif foo is None 表示Python最佳实践。 - Boštjan Mejak

6
一个密切相关的话题:Python的orand短路。在逻辑or操作中,如果任何参数为真,则整个操作将为真,并且不需要评估其他内容; Python会立即返回“true”值。如果完成而没有任何内容为真,则返回它处理的最后一个参数,这将是一个“false”值。 and相反,如果它看到任何假值,则会立即退出并返回该“false”值,或者如果它全部通过,则返回最终的“true”值。
>>> 1 or 2 # first value TRUE, second value doesn't matter
1
>>> 1 and 2 # first value TRUE, second value might matter
2
>>> 0 or 0.0 # first value FALSE, second value might matter
0.0
>>> 0 and 0.0 # first value FALSE, second value doesn't matter
0

1
严格来说,Python不会短路“或”和“与”操作,因为它没有强制求值为True或False,而是返回参数,从而用户可以应用对象的真实性。在这个意义上,RichieHindie的答案非常清晰:对于or,如果第一个参数评估为true,则返回第一个参数,否则返回第二个参数;对于and,它是相反的,如果第一个参数评估为true,则返回第二个参数,否则返回第一个参数。 - Pablo Gutierrez Marques

2

从布尔值的角度来看,它们的行为相同,都返回一个等于false的值。

or 只是“重复使用”它所得到的值,如果左侧的值为true,则返回左侧的值,否则返回右侧的值。


1
Condition1 or Condition2

如果条件1为假,则评估并返回条件2。None表示假。

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