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

问题描述 投票:0回答:7

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

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

有人可以解释一下幕后发生的事情的顺序,以使这项工作按其方式进行吗?

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

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 boolean-logic if-statement
7个回答
32
投票

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

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

x and y

 为真,则 
y
返回
x
,如果
x
为假,则返回
x
a or b
,反之亦然,如果正确则返回
a
,否则返回
b

因此,如果

port == "443"
为 true,则返回
and
的 RHS,即
"https://"
。否则,
and
为 false,因此
or
发挥作用并返回 `"http://", its RHS。

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

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

9
投票
如果左操作数为 true,则

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


6
投票

您真正要问的是像

C and X or Y
这样的表达方式意味着什么或做什么。这是 Python 用户长期运行的早期尝试来代理
C ? X : Y

在大多数情况下它都是有效的,除了,如果

X
False
——这导致了Python代码中的许多错误,所以在Python FAQ中,你会发现更正确的解决方案是
(C and [X] or [Y])[0] 
因为具有单个元素的列表,无论其评估的布尔值如何,始终是
True
!例如:
[None]
True
None
不是。上面的 OP 示例之所以有效,是因为表示
X
的字符串不为空。

但是,所有这一切在 Python 2.5 中都发生了变化,当三元或条件运算符被添加到语言中时,允许您使用更干净的

X if C else Y
,如其他帖子中所述。如果您看到使用旧格式的代码,那是因为用户已经是长期 Python 程序员,尚未采用新语法,他们剪切粘贴其他旧代码,或者他们的雇主仍在使用 2.4.x (或早期版本)等

总而言之,解决您的具体问题会带来一个也被使用的“隐藏功能”,所以让我们仔细看看

return port == "443" and "https://" or "http://"

and
的结合力比
or
更强,这意味着您可以有效地想象这个等效表达式中的一对括号:
(port == "443" and "https://") or "http://"
。此外,我提到的隐藏功能被称为“短路”,这样如果(端口==“443”和“https://”)都为真(它们确实如此),则“or”子句完全成立被忽略。但是,如果其中一个或都不为真,则这是唯一一次使用
or
子句。
另一个观察结果:非空字符串总是 

True

,所以

port == "443"
是唯一可能是
False
,所以这是被问的主要问题。如果为真,则计算移至
and
的右侧,这意味着返回
"https://"
。如果为 false,则会在
"https://" is skipped, and evaluation continues to the right of the 
or` 处发生另一次短路。
代码的底线是:它检查是否为 

port == "443"

,如果是,则返回

"https://
”,否则返回
"http://"
True
False
都不是可能的返回值。最准确的等效是:
定义协议(端口):
如果端口==“443”:
返回“https://”
别的:
返回“http://”

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

定义协议(端口): 如果端口 == “443”,则返回“https://”,否则返回“http://”


2
投票
and

or
的短路行为,并且它们返回其参数之一而不是布尔值。使用此技术有引入难以发现的错误的风险,因此不要在新代码中使用它。

以下是

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://"



1
投票
Python 中 And 和 Or 的特殊性质

中阅读有关 Python 的“与/或技巧”。它有点像 VBA 或 VB 中的 IIF(),或者 C 风格语言中的

?:
    


0
投票

a 和 b -->

if a: return b else: return a

a 或 b -->

if a: return a else: return b



0
投票

    “and”返回第一个 False 项(例如 None、“”、[]、()、{}、0)或最后一个项(如果没有)(例如未找到 False)
  • “or”返回第一个 True 项或最后一个项(例如,未找到 True)**
总结

它们都返回决定语句结果的第一项。 (在最坏的情况下,序列中的最后一项)
  • 注意此规则也适用于链接的所有“and”或所有“or”语句

© www.soinside.com 2019 - 2024. All rights reserved.