&引用;布尔值;Python中的操作(即and/or运算符)

&引用;布尔值;Python中的操作(即and/or运算符),python,boolean-expression,least-astonishment,Python,Boolean Expression,Least Astonishment,此方法搜索第一组单词字符(即:[a-zA-Z0-9!]),返回第一个匹配的组,或在出现故障时返回无 def test(str): m = re.search(r'(\w+)', str) if m: return m.group(1) return None 相同的函数可以重写为: def test2(str): m = re.search(r'(\w+)', str) return m and m.group(1) 这也是一样的,并且

此方法搜索第一组单词字符(即:
[a-zA-Z0-9!]
),返回第一个匹配的组,或在出现故障时返回

def test(str):
    m = re.search(r'(\w+)', str)
    if m:
        return m.group(1)
    return None
相同的函数可以重写为:

def test2(str):
    m = re.search(r'(\w+)', str)
    return m and m.group(1)
这也是一样的,并且是记录在案的行为;正如明确指出的那样:

表达式
x和y
首先计算
x
;如果
x
为false,则返回其值;否则,将计算
y
,并返回结果值

然而,作为一个布尔运算符(手册上甚至有这样的说明),我希望
返回布尔值。结果,当我发现这是如何工作的时候,我感到很惊讶


还有什么其他的使用案例,和/或这种相当不直观的实现的基本原理是什么?

我并不觉得奇怪,事实上,当我最初尝试它时,我希望它能工作

虽然并非所有值都是布尔值,但请注意,实际上,所有值都是布尔值——它们表示真值。(在Python中,
bool
实际上是一个只表示true或false的值。)数字
0
不是bool,但它(在Python中)显式地具有一个布尔值false

换句话说,布尔运算符
并不总是返回一个
bool
,但它总是返回一个布尔值;表示真或假的信息,即使它还有其他逻辑附加的信息(如字符串)

也许这是追溯性的理由;我不确定,但不管怎样,Python的布尔运算符的行为都很自然


什么时候使用

在您的示例中,test2对我来说更清晰。我可以看出它们的作用是一样的:test2中的构造并没有使它更难理解。在所有其他条件相同的情况下,test2中更简洁的代码(稍微)更容易理解。也就是说,这只是一个微不足道的区别,我也不太愿意去重写任何东西

它在其他方面也同样有用:

a = {
    "b": a and a.val,
    "c": b and b.val2,
    "d": c and c.val3,
}
这可以用不同的方式重写,但这是清晰、直接和简洁的


不要过火;“a()和b()或c()”作为“a()?b():c()”的替代品是危险和令人困惑的,因为如果b()为false,您将以c()结束。如果要编写三元语句,请使用三元语法,即使它非常难看:
b()如果a()或c()

基本上
a和b
返回与整个表达式具有相同真值的操作数

这听起来可能有点让人困惑,但只要在你的头脑中这样做:如果
a
False
,那么
b
就不再重要了(因为
False和任何
都将是
False
),所以它可以立即返回
a

但是当
a
True
时,只有
b
起作用,因此它会立即返回
b
,甚至不看一眼

这是许多语言所做的一种非常常见且非常基本的优化

这个的其他用例是什么

没有

这种相当不直观的实现的基本原理是什么

“不直观”?真正地我不同意

让我们想想

如果
a
为假,则“ab”为假。因此,第一个假值足以知道答案。为什么要麻烦将
a
转换为另一个布尔值?这已经是假的了。
false
的错误率还要高多少?同样错误,对吗

所以
a
的值——当与
False
相等时——就足够假了,所以这就是整个表达式的值。无需进一步转换或处理。完成了

a
的值等于
True
时,就只需要
b
的值。无需进一步转换或处理。为什么要将
b
转换为另一个布尔值?我们只需要知道它的价值。如果它像
True
,那么它就足够真实了。还有多少是正确的

为什么要创建虚假的附加对象

进行相同的分析

为什么要转换为布尔值?这已经足够真实或者足够虚假了。它还能有多真实?


试试这个

>>> False and 0
False
>>> True and 0
0
>>> (True and 0) == False
True
虽然
(True和0)
实际上是
0
,但它等于
False
。就所有实际目的而言,这都是错误的

如果是问题,那么
bool(a和b)
将强制显式转换

这个的其他用例是什么

简洁性(因此,一旦你习惯了它,就会清晰,因为毕竟它根本不会牺牲可读性!-)任何时候你都需要检查某个东西,如果它是真的,就使用该东西,如果它是假的,就使用另一个值(这是针对
——将其反转为
——我非常有意地避免使用实际关键字或类似的
True
False
,因为我谈论的是每个对象,而不仅仅是
bool
!-)

任何计算机屏幕上的垂直空间都是有限的,如果有选择,最好将其用于有用的可读性辅助工具(文档字符串、注释、战略性地放置空行以分隔块等),而不是转行,例如:

inverses = [x and 1.0/x for x in values]
分为六类,例如:

inverses = []
for x in values:
    if x:
        inverses.append(1.0/x)
    else:
        inverses.append(x)
或者更狭窄的版本

和/或其理由是什么 相当不直观的实现

初学者非但不是“不直观”,反而经常被某些语言(如标准帕斯卡语)所绊倒没有具体说明
的求值顺序和短路性质;Turbo Pascal和语言标准之间的一个区别就是Turbo实现了
,而语言标准在当时使Turbo成为所有时代最流行的Pascal方言