出于某种原因,这个功能让我感到困惑:
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 中的某种特殊情况,还是我完全误解了语句的工作原理?
这是一个古老的习语;插入括号以显示优先级,
(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://"
and
返回右操作数。如果左操作数为 false,则 or
返回右操作数。否则它们都返回左操作数。据说它们会合并。
您真正要问的是像
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://”
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://"
a 和 b -->
if a:
return b
else:
return a
a 或 b -->
if a:
return a
else:
return b
:
它们都返回决定语句结果的第一项。 (在最坏的情况下,序列中的最后一项)