“布尔” Python 中的运算(即:和/或运算符)

发布于 2024-09-25 19:27:35 字数 797 浏览 1 评论 0原文

此方法搜索第一组单词字符(即:[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)

这工作原理相同,并且是记录的行为;正如此页面明确指出的那样:

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

然而,作为一个布尔运算符(甚至在手册上也这么说),我期望 and 返回一个布尔值。结果,当我发现这是如何工作的时,我惊讶

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

This method searches for the first group of word characters (ie: [a-zA-Z0-9_]), returning the first matched group or None in case of failure.

def test(str):
    m = re.search(r'(\w+)', str)
    if m:
        return m.group(1)
    return None

The same function can be rewritten as:

def test2(str):
    m = re.search(r'(\w+)', str)
    return m and m.group(1)

This works the same, and is documented behavior; as this page clearly states:

The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.

However, being a boolean operator (it even says so on the manual), I expected and to return a boolean. As a result, I was astonished when I found out (how) this worked.

What are other use cases of this, and/or what is the rationale for this rather unintuitive implementation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

暗恋未遂 2024-10-02 19:27:35

这还有哪些其他用例,

简洁(因此一旦您习惯了它,就变得清晰,因为毕竟它根本不会牺牲可读性!-)如果它是 true,则使用该值,如果该值是 false,则使用另一个值(即 and - 将其反转为 or - 我是 非常刻意避免使用实际的关键字或类似的TrueFalse,因为我正在谈论每个对象,不仅仅是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)没有指定求值顺序以及 和 的短路性质而被绊倒。代码>和<代码>或; Turbo Pascal 和语言标准之间的区别之一正是 Turbo 实现了 andor,而语言标准在当时使 Turbo 成为有史以来最流行的 Pascal 方言。就像后来的 Python 所做的那样(以及更早的 C 语言所做的......)。

What are other use cases of this,

Conciseness (and therefore clarity, as soon as you get used to it, since after all it does not sacrifice readability at all!-) any time you need to check something and either use that something if it's true, or another value if that something is false (that's for and -- reverse it for or -- and I'm very deliberately avoiding the actual keywords-or-the-like True and False, since I'm talking about every object, not just bool!-).

Vertical space on any computer screen is limited, and, given the choice, it's best spent on useful readability aids (docstrings, comments, strategically placed empty lines to separate blocks, ...) than in turning, say, a line such as:

inverses = [x and 1.0/x for x in values]

into six such as:

inverses = []
for x in values:
    if x:
        inverses.append(1.0/x)
    else:
        inverses.append(x)

or more cramped versions thereof.

and/or what is the rationale for this
rather unintuitive implementation?

Far from being "unintuitive", beginners regularly were tripped up by the fact that some languages (like standard Pascal) did not specify the order of evaluation and the short-circuiting nature of and and or; one of the differences between Turbo Pascal and the language standard, which back in the day made Turbo the most popular Pascal dialect of all times, was exactly that Turbo implemented and and or much like Python did later (and the C language did earlier...).

风流物 2024-10-02 19:27:35

这还有哪些其他用例,

没有。

这种相当不直观的实现的理由是什么?

“不直观”?真的吗?我不同意。

我们想一想。

如果a为假,则“ab”被伪造。所以第一个假值足以知道答案。为什么要把 a 转换为另一个布尔值呢?已经是假的了。 False 到底有多假?同样是假的,对吧?

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

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

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

的分析相同。

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


试试这个。

>>> False and 0
False
>>> True and 0
0
>>> (True and 0) == False
True

虽然 (True and 0) 实际上是 0,但它等于 False。对于所有实际目的来说,这都是错误的。

如果存在问题,则 bool(a and b) 将强制显式转换。

What are other use cases of this,

No.

what is the rationale for this rather unintuitive implementation?

"unintuitive"? Really? I'd disagree.

Let's think.

"a and b" is falsified if a is false. So the first false value is sufficient to know the answer. Why bother transforming a to another boolean? It's already false. How much more false is False? Equally false, right?

So a's value -- when equivalent to False -- is false enough, so that's the value of the entire expression. No further conversion or processing. Done.

When a's value is equivalent to True then b's value is all that's required. No further conversion or processing. Why transform b to another boolean? It's value is all we need to know. If it's anything like True, then it's true enough. How much more true is True?

Why create spurious additional objects?

Same analysis for or.

Why Transform to Boolean? It's already true enough or false enough. How much more True can it get?


Try This.

>>> False and 0
False
>>> True and 0
0
>>> (True and 0) == False
True

While (True and 0) is actually 0, it's equal to False. That's false-enough for all practical purposes.

If it's a problem, then bool(a and b) will force the explicit conversion.

一笑百媚生 2024-10-02 19:27:35

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

这可能听起来有点令人困惑,但只要在你的脑海中做一下:如果 aFalse,那么 b 就不再重要了(因为 aFalse,那么 b 就不再重要了(因为>False 和任何内容 都将始终为False),因此它可以立即返回a

但是,当 aTrue 时,只有 b 重要,因此它会立即返回 b,甚至无需查看。

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

Basically a and b returns the operand that has the same truth value as the whole expression.

It might sound a bit confusing but just do it in your head: If a is False, then b does not matter anymore (because False and anything will always be False), so it can return a right away.

But when a is True then only b matters, so it returns b right away without even looking.

This is a very common and very basic optimization many languages do.

伴随着你 2024-10-02 19:27:35

我认为,虽然这种表示法“有效”,但它代表了一种隐藏逻辑的糟糕编码风格,并且会让经验丰富的程序员感到困惑,因为他们掌握了大多数其他语言如何工作的“包袱”。

在大多数语言中,活动函数的返回值由函数的类型决定。除非它被明确超载。例如,“strlen”类型函数应返回整数而不是字符串。

诸如核心关节炎和逻辑函数(+-/*|&!)之类的直线函数甚至更加受到限制,因为它们背后也有形式数学理论的历史。 (考虑有关这些函数的操作顺序的所有参数)

让基本函数返回除最常见数据类型(逻辑或数字)之外的任何内容,应将其归类为有目的的混淆。

几乎所有通用语言中的“&”或“&&”或“AND”是逻辑或布尔函数。在幕后,优化编译器可能会在逻辑流中使用如上所述的快捷逻辑,但不会使用数据结构修改(任何以这种方式更改值的优化编译器都将被视为损坏),但如果该值预计用于变量中为了进一步处理,它应该是逻辑或布尔类型,因为在大多数情况下这是这些运算符的“形式”。

I think that while this notation 'works' it represents a poor coding style that hides logic and will confuse more experienced programmers who will have the 'baggage' of knowledge how the majority of other languages work.

In most languages the return value of an active function is determined by the type of function. Unless its's been explicitly overloaded. Example a 'strlen' type function is expected to return an integer not a string.

In line functions such as the core arthritic and logic functions (+-/*|&!) are even more restrained because they also have history of formal math theory behind them. (Think about all the arguments about order of operations for these functions)

To have fundamental functions return anything but their most common data type (either logic or numeric) should be classified as purposeful obfuscation.

In just about every common language '&' or '&&' or 'AND' is a logic or Boolean function. Behind the scenes, optimization compilers might use short cutting logic like above in LOGIC FLOW but not DATA STRUCTURE Modification (any optimizing compiler that changed the value this way would have been considered broken), but if the value is expected to be used in a variable for further processing, it should be in the logic or boolean type because that's the 'formal' for these operators in the majority of circumstances.

娇纵 2024-10-02 19:27:35

我并不觉得这令人惊讶,事实上,当我最初尝试它时,我就预计它会起作用。

虽然并非所有值都是布尔值,但请注意,实际上所有值都是布尔值——它们代表真值。 (在 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() and b() or c()”作为“a()? b():c()”的替代品是危险且令人困惑的,因为如果 b() 是,你最终会得到 c()错误的。如果您正在编写三元语句,请使用三元语法,即使它非常丑陋:b() if a() else c()

I didn't find this surprising, and in fact expected it to work when I originally tried it.

While not all values are bools, note that in effect, all values are boolean--they represent a truth value. (In Python, a bool is--in effect--a value which only represents true or false.) The number 0 isn't a bool, but it explicitly (in Python) has a boolean value of False.

In other words, the boolean operator and doesn't always return a bool, but it always return a boolean value; one that represents true or false, even if it also has other information logically attached to it (eg. a string).

Maybe this is retroactive justification; I'm not sure, but either way it seems natural for Python's boolean operators to behave as they do.


When to use it?

In your example, test2 feels clearer to me. I can tell what they both do equally: the construction in test2 doesn't make it any harder to understand. All else equal, the more concise code in test2 is--marginally--more quickly understood. That said, it's a trivial difference, and I don't prefer either enough that I'd jump to rewrite anything.

It can be similarly useful in other ways:

a = {
    "b": a and a.val,
    "c": b and b.val2,
    "d": c and c.val3,
}

This could be rewritten differently, but this is clear, straightforward and concise.

Don't go overboard; "a() and b() or c()" as a substitute for "a()? b():c()" is dangerous and confusing, since you'll end up with c() if b() is false. If you're writing a terniary statement, use the terniary syntax, even though it's hideously ugly: b() if a() else c().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文