“and”和“or”组合在一个语句中如何工作?[复制]

How do "and" and "or" work when combined in one statement? [duplicate]

提问人:orokusaki 提问时间:4/6/2010 最后编辑:Abelorokusaki 更新时间:11/10/2023 访问量:26133

问:

出于某种原因,这个功能让我感到困惑:

def protocol(port):
    return port == "443" and "https://" or "http://"

有人可以解释一下幕后发生的事情的顺序,以使它以这种方式工作。

在我尝试之前,我理解它是这样的:

Either A)

def protocol(port):
    if port == "443":
        if bool("https://"):
            return True
    elif bool("http://"):
        return True
    return False

或 b)

def protocol(port):
    if port == "443":
        return True + "https://"
    else:
        return True + "http://"

这是 Python 中的某种特殊情况,还是我完全误解了语句的工作原理?

python 布尔逻辑 if-statement

评论

0赞 orokusaki 4/6/2010
@Responders,请参阅我的 1 分钟后更新。不好意思。
1赞 João Portela 4/6/2010
请记住,“and”和“or”语句返回要计算的最后一个表达式。:)

答:

9赞 Ignacio Vazquez-Abrams 4/6/2010 #1

and如果 left 为 true,则返回右操作数。 如果 left 为 false,则返回右操作数。否则,它们都返回左操作数。据说它们会合并or

评论

0赞 orokusaki 4/6/2010
啊,谢谢伊格纳西奥。在不了解这一点的情况下,我不知道我是如何在 Python 中走到这一步的。这是我第一次看到它完全像这样使用。+1
32赞 Alex Martelli 4/6/2010 #2

这是一个古老的成语;插入括号以显示优先级,

(port == "443" and "https://") or "http://"

x and y如果是真的,如果是假的,则返回;,反之亦然,如果它是 Truish,则返回,否则.yxxxa or bab

因此,如果为 true,则返回 的 RHS,即 。否则,the 是 false,所以 开始发挥作用并返回 '“http://”,即它的 RHS。port == "443"and"https://"andor

在现代 Python 中,翻译这个古老成语的更好方法是:

"https://" if port == "443" else "http://"

评论

0赞 orokusaki 4/6/2010
@Alex +1 感谢您的深入解释。他们显然已经做到了,所以我在 10 分钟内无法接受答案:(但很好的答案。
0赞 Alex Martelli 4/6/2010
@orokusaki,谢谢,我相信你以后会接受的;-)。
0赞 tosh 4/6/2010
+1 提及 Python 的三元运算符,恕我直言,更容易阅读/理解
1赞 the Tin Man 4/6/2010
很久以前,我就学会了使用括号来使解释器/编译器做我想让代码做的事情,而不是受制于优先级。它有助于为我和任何在我传递代码后维护它的人记录代码。我认为这是防御性编码的一部分。
2赞 Mark Byers 4/6/2010 #3

这是一个不推荐的丑陋黑客。它之所以有效,是因为 和 的短路行为,并且它们返回的是它们的参数之一,而不是布尔值。使用此技术可能会引入难以发现的 bug,因此不要在新代码中使用它。andor

下面是一个成语如何给出意外结果的示例:and/or

>>> foo = 'foobar'
>>> bar = 'foobar'
>>> x = 0
>>> y = 1
>>> (foo == bar) and x or y   # Will this return the value of x if (foo == bar)?
1

最好使用较新的表示法:

return "https://" if port == "443" else "http://"

评论

0赞 orokusaki 4/6/2010
@Mark 这是我熟悉的版本,直到今天我才在我的帖子中看到过这个版本。+1
1赞 Abel 4/6/2010 #4

您可能想阅读本文 Python 中 And and or 的特殊性质 Python 的“和/或技巧”。这有点像 VBA 或 VB 或 C 样式语言。IIF()?:

评论

0赞 orokusaki 4/6/2010
@Abel 谢谢。我刚刚读了它,有趣的文章。我已经大量使用了该语法,但由于某种原因,此代码片段没有 jive。return a or b
0赞 Yaroslav 4/6/2010 #5

此构造之所以有效,是因为它“展开”为以下代码:

a 和 b -->

if a:
  return b
else:
  return a

a 或 b -->

if a:
  return a
else:
  return b
6赞 wescpy 4/6/2010 #6

你真正要问的是表达式的含义或作用。这是 Python 用户长期进行的早期尝试,用于代理C and X or YC ? X : Y

在大多数情况下,它有效,除非是 - 这导致了 Python 代码中的许多错误,因此在 Python FAQ 中,您会发现更正确的解决方案是因为具有单个元素的列表,无论其计算的布尔值如何,始终是 !例如:is but isn't。上面的 OP 示例之所以有效,是因为表示的字符串不为空。XFalse(C and [X] or [Y])[0]True[None]TrueNoneX

然而,这一切都在 Python 2.5 中发生了变化,当三元或条件运算符被添加到语言中时,允许您使用此处其他帖子中所述的清洁器。如果您看到使用旧格式的代码,那是因为用户已经是长期的 Python 程序员,尚未采用新语法,他们剪切粘贴其他旧代码,或者他们的雇主仍在使用 2.4.x(或更早版本)等。X if C else Y

综上所述,解决您的具体问题会带来一个“隐藏功能”,因此让我们仔细看看:return port == "443" and "https://" or "http://"

绑定比 强,这意味着您可以有效地想象这个等效表达式中的一对括号:。此外,我提到的隐藏特征被称为短路,因此,如果两个(端口 == “443”和“https://”)都为真(它们是),则该子句将被完全忽略。但是,如果一个或两者都不为真,则这是唯一使用该子句的时间。andor(port == "443" and "https://") or "http://"oror

另一个观察:非空字符串总是 ,所以唯一可能的东西是 ,所以这是被问到的主要问题。如果为 true,则 evaluation 移动到 的右侧,返回 meaning 。如果为 false,则在跳过的位置发生另一次短路,并且计算继续在 的右侧进行。Trueport == "443"Falseand"https://""https://"or

代码的作用的底线:它检查是否 ,如果是,则返回 “,否则返回。返回值既不是,也可能是返回值。最准确的等价物是:port == "443""https://"http://"TrueFalse

def protocol(port):
    if port == "443":
        return "https://"
    else:
        return "http://"

在现代 Python 中,你可以这样写:

def protocol(port):
    return "https://" if port == "443" else "http://"

最后一个假设是,这是一个字符串。更健壮的版本将支持整数输入,例如 .portreturn "https://" if str(port) == "443" else "http://"

0赞 Zhenhua 8/2/2017 #7

有了所有好的答案,我发现这些陈述可以帮助我更好地记住这一点,并适合我的大脑工作方式(希望能有更多人):

  • “and” 返回第一个 False 项(例如,None、“”、“[]、()、{}、0)或最后一个 False 项(例如,未找到 False)

  • “or” 返回第一个 True 项或最后一个项(例如,未找到 True)**

综上所述

  • 它们都返回决定语句结果的第一个项目。(在最坏的情况下,序列中的最后一项)

请注意,此规则也适用于链接的 all “and” 或 all “or” 语句