这个“and”语句实际上在返回中做了啥?

Posted

技术标签:

【中文标题】这个“and”语句实际上在返回中做了啥?【英文标题】:What is this "and" statement actually doing in the return?这个“and”语句实际上在返回中做了什么? 【发布时间】:2013-06-21 17:23:31 【问题描述】:

我试图更好地理解下面的python代码以及作者为什么在return中使用“AND”语句。

def valid_password(self, password):
        PASS_RE = re.compile(r'^.6,128$')
        return password and PASS_RE.match(password)

进一步的代码...

if not self.valid_password(self.password):
    params['error_password'] = "Please enter a valid password."

我尝试检查返回给调用者的结果对象,但我仍然不完全理解它是如何工作的。

似乎这会将密码返回给调用者以及密码是否有效的布尔值,但是我不明白调用函数如何检查对象的布尔值?这是我错过的关于 Python 的基本知识吗?

在这个例子旁边还有另一个类似用法的例子,但是它使用了“或”语句,这对我来说更令人困惑:

def valid_email(self, email):
    EMAIL_RE  = re.compile(r'^[\S]+@[\S]+\.[\S]+$')
    return not email or EMAIL_RE.match(email)

任何关于这里到底发生了什么的建议将不胜感激。该代码可以正常工作并执行您期望它执行的操作,根据正则表达式验证输入并返回 True 或 False,但是我真的很想了解它是这样写的,而不是简单地返回 bool。

【问题讨论】:

嘿,伙计,我试图在我的回答中解释用于这些表达式的构建块,基本上是短路评估和 python 真值——它们是任何语言的重要概念。如果您需要更多说明,请告诉我。 【参考方案1】:

在 Python 中,andor 都将返回它们的操作数之一。使用or,Python 检查第一个操作数,如果它是“真实”值(稍后将详细介绍真实性),它会返回第一个值而不检查第二个值(这称为布尔快捷评估,它可能很重要) .如果第一个是“falsey”,那么 Python 返回第二个操作数,不管它是什么:

Python 2.7.3 (default, Jan  2 2013, 13:56:14)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 2 or 3
2
>>> 0 or 3
3

使用“and”,会发生很多相同的事情:首先检查第一个操作数,如果它是“假”,那么 Python 永远不会检查第二个操作数。如果第一个操作数是“真”,那么 Python 返回第二个操作数,不管它是什么:

>>> 2 and 3
3
>>> 0 and 3
0
>>> 3 and 0
0
>>> 3 and []
[]
>>> 0 and []
0

现在我们来谈谈“真”和“假”。 Python 使用以下规则在布尔上下文中评估事物:

以下值为“falsey”:False、None、0(零)、[](空列表)、()(空元组)、(空字典)、空集、“” (空字符串) 其他一切都是“真实的”

所以像 password and PASS_RE.match(password) 这样的东西正在利用 Python 的短路评估。如果password 是None,那么and 运算符将只返回None,并且永远不会评估后半部分。这很好,因为PASS_RE.match(None) 会抛出异常。观看:

>>> 3 or []
3
>>> [] or 3
3
>>> 0 or []
[]
>>> [] or 0
0
>>> 0 and []
0
>>> [] and 0
[]

看看短路是如何工作的?现在看这个:

>>> value = "hello"
>>> print (value.upper())
HELLO
>>> print (value and value.upper())
HELLO
>>> value = None
>>> print (value.upper())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'upper'
>>> print (value and value.upper())
None

了解and 的短路功能如何帮助我们避免回溯?这就是这个函数中发生的事情。

【讨论】:

事实上,其他答案恰好有一半是正确的。所以这个答案是不正确,因为它声称大多数其他答案都是不正确的。而且我还是不喜欢“真”和“假”,因为这暗示着它们“有点真”或“有点假”。 当我开始写这篇文章时,它肯定是“最”的。 :-) 我认为当时有三个答案,只有一个没有说“这会返回一个布尔值”。 显示在可以编辑答案时编写此类内容的危险。 :-) 我想我会编辑我的说“几个”其他答案不正确。 :-) @LennartRegebro 虽然“有点真实”和“有点虚假”与呃,真相并不太远,因为“x 是真实的”意味着bool(x) == True,但不一定是x == True .【参考方案2】:

有问题的行验证密码是'truthy',并且它与预定义的密码正则表达式匹配。

下面是它的分解方式:

如果password是'falsey',函数返回password

如果密码为'truthy',但密码与密码正则表达式不匹配,则函数返回None

如果存在“真实”密码,并且与正则表达式匹配,则为 match object is returned。

and 运算符是“短路”运算符;如果第一个值是 'truthy',则返回第二个值。否则,它返回第一个值。

您可以查看this page 以了解在 python 中哪些类型的东西是“真实的”。

【讨论】:

“truthy”和“falsey”......呃......“测试为真”和“测试为假”怎么样? @LennartRegebro 这是因为它们并不是真正的 True 布尔值,如果在布尔上下文中使用它们只是碰巧评估为 True。查看我的答案,了解使用字符串的布尔表达式示例。 'truthy' 和 'falsey' 是谈论这些事情的方式,也是描述性的。 'foo' 是真实的,但 'foo' != True。 '' 是假的,但 '' != 假的。 我以前从未听说过,我已经讨厌它了。这听起来像“不假但几乎”,这是假的。 :-) 这不是模糊逻辑。 在你的第三点,如果第一个值是-truthy-,那么它返回第二个值。【参考方案3】:

你只需要知道:

    Python 中的空字符串计算结果为 False (also None, empty lists, and other "zero" types)。 布尔表达式经过称为short-circuit evaluation 的优化

因此,

a = '1'
print('' and a)

... 打印空字符串,因为它是 False,表达式永远不会是 True,并且第二部分(a)甚至都不会被计算。

a = '1'
print('' or a)

打印'1',因为空字符串为False,所以必须对第二部分求值以给出表达式的结果。

【讨论】:

以上是关于这个“and”语句实际上在返回中做了啥?的主要内容,如果未能解决你的问题,请参考以下文章

“()”在等级声明中做了啥

Include() 在 LINQ 中做了啥?

apply_filters(...) 实际上在 WordPress 中做了啥?

哈希在python中做了啥?

“信任代理”实际上在 express.js 中做了啥,我需要使用它吗?

自动恢复在 Apache Pulsar 中做了啥?