提问人:NullUserException 提问时间:9/30/2010 更新时间:11/27/2014 访问量:6699
Python 中的“布尔”运算(即:and/或运算符)
"Boolean" operations in Python (ie: the and/or operators)
问:
此方法搜索第一组单词字符(即:),返回第一个匹配的组或失败。[a-zA-Z0-9_]
None
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)
这同样有效,并且是记录在案的行为;正如本页明确指出的:
表达式首先计算 ;如果为 false,则返回其值;否则,将进行计算并返回结果值。
x and y
x
x
y
但是,作为一个布尔运算符(它甚至在手册上这么说),我希望返回一个布尔值。结果,当我发现(如何)这是如何工作的时,我感到很惊讶。and
还有哪些其他用例,和/或这种相当不直观的实现的基本原理是什么?
答:
我并不觉得这令人惊讶,事实上,当我最初尝试它时,我就希望它能起作用。
虽然并非所有值都是 ,但请注意,实际上,所有值都是布尔值 - 它们表示真值。(在 Python 中,is--in 效果 - 一个仅表示 true 或 false 的值。该数字不是布尔值,但它显式(在 Python 中)具有布尔值 False。bools
bool
0
换句话说,布尔运算符并不总是返回一个 ,但它总是返回一个布尔值;一个表示真或假的,即使它还在逻辑上附加了其他信息(例如字符串)。and
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() 是假的,你最终会得到 c()。如果你正在编写三元语句,请使用三元语法,即使它丑陋得可怕:.b() if a() else c()
评论
基本上返回与整个表达式具有相同真值的操作数。a and b
这听起来可能有点令人困惑,但只要在脑海中做:如果是,那么就不再重要了(因为永远是),所以它可以立即返回。a
False
b
False and anything
False
a
但是什么时候才重要,所以它甚至不用看就马上回来了。a
True
b
b
这是许多语言都会做的非常常见且非常基本的优化。
评论
还有哪些其他用例,
不。
这种相当不直观的实现的基本原理是什么?
“不直观”?真?我不同意。
让我们想一想。
如果“A 和 B”为假,则为伪造。因此,第一个错误值足以知道答案。为什么要费心转换为另一个布尔值?这已经是假的了。还有多少假?同样是错误的,对吧?a
a
False
所以 的值 -- 当等价于 -- 时,是足够假的,所以这就是整个表达式的值。无需进一步转换或处理。做。a
False
当 的值等于 时,只需要 的值。无需进一步转换或处理。为什么要转换为另一个布尔值?它的价值是我们需要知道的。如果它像 ,那么它就足够真实了。还有多少真实?a
True
b
b
True
True
为什么要创建虚假的附加对象?
对 or 的分析相同。
为什么要转换为布尔值?它已经足够真实或足够虚假了。它还能得到多少真实?
试试这个。
>>> False and 0
False
>>> True and 0
0
>>> (True and 0) == False
True
而实际上,它等于 。对于所有实际目的来说,这都是错误的。(True and 0)
0
False
如果这是一个问题,那么将强制进行显式转换。bool(a and b)
还有哪些其他用例,
简洁(因此清晰,一旦你习惯了它,因为毕竟它根本不会牺牲可读性!-)任何时候你需要检查一些东西,如果它是真的,要么使用那个东西,或者如果那个东西是假的,则使用另一个值(那是为了--反转它--我非常刻意地避免使用实际的关键字-or-the-like和, 因为我说的是每个对象,而不仅仅是!and
or
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 成为有史以来最流行的 Pascal 方言,正是 Turbo 实现的,就像 Python 后来所做的那样(以及更早的 C 语言......and
or
and
or
评论
x and 1.0/x for ...
and
or
我认为,虽然这种符号“有效”,但它代表了一种糟糕的编码风格,它隐藏了逻辑,并且会让更有经验的程序员感到困惑,他们将拥有大多数其他语言如何工作的“包袱”。
在大多数语言中,活动函数的返回值由函数的类型决定。除非它被明确重载。示例:“strlen”类型函数应返回整数而不是字符串。
诸如核心关节炎和逻辑函数(+-/*|&!)之类的在线函数更加受到限制,因为它们背后也有形式数学理论的历史。(想想所有关于这些函数的运算顺序的争论)
要让基本函数返回除其最常见的数据类型(逻辑或数字)之外的任何内容,应归类为有目的的混淆。
在几乎所有通用语言中,“&”或“&&”或“AND”都是一个逻辑或布尔函数。在幕后,优化编译器可能会在 LOGIC FLOW 中使用如上所述的短切逻辑,但不会使用 DATA STRUCTURE Modification(任何以这种方式更改值的优化编译器都会被视为损坏),但如果该值预期在变量中用于进一步处理,它应该是逻辑或布尔类型,因为在大多数情况下,这是这些运算符的“正式”。
评论
if...else
??
return m and m.group(1)
m is not None and...