此方法搜索第一组单词字符(即:[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)
这是相同的,并且是记录在案的行为;正如this page明确指出:
表达式
x and y
首先评估x
;如果x
为false,则返回其值;否则,将评估y
并返回结果值。
然而,作为一个布尔运算符(它甚至在手册上都这么说),我期望and
返回一个布尔值。结果,当我发现(如何)这有效时,我astonished。
这有什么其他用例,和/或这种相当不直观的实现的理由是什么?
答案 0 :(得分:6)
这有什么其他用例,
简洁(因此清晰,一旦你习惯它,因为毕竟它不牺牲可读性! - )任何时候你需要检查一些东西并使用那些东西如果它是真的,或者如果某些东西是假的(或者是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)
或其更狭窄的版本。
和/或这是什么原因 相当不直观的实施?
由于某些语言(如标准Pascal)不指定评估顺序和{{1的短路性质 - 这一事实,初学者经常被“不直观”所困扰。 }和and
; Turbo Pascal和语言标准之间的差异之一,在当天使Turbo成为有史以来最受欢迎的Pascal方言,正是Turbo实现了or
和and
,就像Python后来做的那样(而C语言早先做过......)。
答案 1 :(得分:4)
这有什么其他用例,
没有。
这种相当不直观的实施的理由是什么?
“直观”?真?我不同意。
让我们思考一下。
如果a
为false,则“a 和 b”会被伪造。所以第一个假值足以知道答案。为什么还要将a
转换为另一个布尔值?这已经是假的。 False
还有多少错误?同样错,对吧?
所以a
的值 - 当等于False
时 - 足够假,所以这是整个表达式的值。没有进一步的转换或处理。完成。
当a
的值等于True
时,b
的值就是所需要的。没有进一步的转换或处理。为什么要将b
转换为另一个布尔值?这是我们需要知道的全部价值。如果它像True
那样,那就足够了。 True
还有多少呢?
为什么要创建虚假的附加对象?
或的相同分析。
为什么要转换为布尔值?它已经足够或足够假。真的可以获得多少呢?
试试这个。
>>> False and 0
False
>>> True and 0
0
>>> (True and 0) == False
True
虽然(True and 0)
实际上是0
,但它等于False
。这对于所有实际目的来说都是错误的。
如果这是一个问题,那么bool(a and b)
将强制进行显式转换。
答案 2 :(得分:0)
我没有发现这令人惊讶,事实上我希望它在我最初尝试时能够正常工作。
虽然并非所有值都是bools
,但请注意,实际上,所有值都是 boolean - 它们代表真值。 (在Python中,bool
实际上是仅表示true或false的值。)数字0
不是bool,而是明确的(在Python中)的布尔值为False。
换句话说,布尔运算符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()
。
答案 3 :(得分:0)
基本上a and b
返回与整个表达式具有相同真值的操作数。
这可能听起来有些令人困惑,但只是在脑海中这样做:如果a
是False
,则b
不再重要(因为False and anything
将永远是False
),因此它可以立即返回a
。
但当a
为True
时,只有b
很重要,所以它会立即返回b
,而不会看。
这是许多语言都非常常见且非常基本的优化。
答案 4 :(得分:0)
我认为虽然这种符号可以使用'它代表了一种糟糕的编码风格,隐藏了逻辑,并且会让更多有经验的程序员感到困惑,他们将拥有这样的行李'了解大多数其他语言的工作原理。
在大多数语言中,活动函数的返回值由函数类型决定。除非它被明确重载。示例a' strlen' type函数应该返回一个不是字符串的整数。
核心关节炎和逻辑功能(+ - / * |&!)等在线功能更加克制,因为它们背后还有正式数学理论的历史。 (想想关于这些函数的操作顺序的所有论点)
要使基本函数返回任何内容,但应将其最常见的数据类型(逻辑或数字)归类为有目的的混淆。
几乎所有的共同语言'&'或者'&&'或者' AND'是逻辑或布尔函数。在幕后,优化编译器可能在LOGIC FLOW中使用如上所述的短切割逻辑,但不使用数据结构修改(任何以这种方式改变值的优化编译器都会被视为已损坏),但是如果该值预期用于变量为了进一步处理,它应该是逻辑或布尔类型,因为它是“正式的”#39;对于大多数情况下的这些运营商。