“与”和“或”在一个语句中如何组合使用?

12 投票
7 回答
27413 浏览
提问于 2025-04-15 21:15

这个函数让我有点困惑:

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中的某种特殊情况吗?还是我完全搞错了语句是怎么运作的?

7 个回答

6

你真正想问的是像 C and X or Y 这样的表达式是什么意思或有什么作用。这是Python用户早期尝试用来代替 C ? X : Y 的一种方式。

大部分情况下,这种写法是有效的,如果 XFalse,就会出现问题,这导致了很多Python代码中的bug。因此在 Python常见问题解答 中,你会发现更正确的写法是 (C and [X] or [Y])[0],因为一个只有一个元素的列表,无论它的布尔值是什么,都会被认为是 True!例如: [None]True,但 None 不是。上面提到的例子之所以有效,是因为表示 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://"。此外,我提到的隐藏特性被称为 短路,也就是说如果 (port == "443" and "https://") 都为真(实际上是的),那么 or 的部分会被完全忽略。然而,如果其中一个或两个都不为真,只有在这种情况下 or 的部分才会被使用。

还有一点需要注意:非空字符串总是被认为是 True,所以 port == "443" 是唯一可能为 False 的部分,因此这是主要的问题。如果它为真,评估就会移动到 and 的右边,也就是说会返回 "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://"

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

9

and这个操作符的意思是,如果左边的值是真的(也就是有意义的),那么就返回右边的值。or这个操作符则是,如果左边的值是假的(也就是没有意义的),那么就返回右边的值。否则,它们都会返回左边的值。我们可以说它们是合并的意思。

32

这是一个比较老的说法;用括号来表示优先级。

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

x and y 的意思是,如果 x 是“真”的话,就返回 y;如果 x 是“假”的话,就返回 x。而 a or b 则正好相反,如果 a 是“真”的话,就返回 a,否则返回 b

所以,如果 port == "443" 是真的,这个表达式就会返回 and 右边的部分,也就是 "https://"。如果不是,那么 and 就是假的,这时就会用到 or,返回 "http://",也就是它右边的部分。

在现代的 Python 中,有一种更好的方式来表达这个比较老的说法:

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

撰写回答