为什么在Python中'and'和'or'会返回操作数?

2024-10-01 13:34:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在检查LPTHW,我遇到了一些我无法理解的事情。什么时候你希望你的布尔值and或{}返回布尔值以外的值?LPTHW文本指出,所有像python这样的语言都有这种行为。他指的是解释语言与编译语言,还是鸭子类型语言与静态类型语言?在

我运行了以下代码:

>>> False and 1
False
>>> True and 1
1
>>> 1 and False
False
>>> 1 and True
True
>>> True and 121
121
>>> False or 1
1
>>> False or 112
112
>>> False or "Khadijah"
'Khadijah'
>>> True and 'Khadijah'
'Khadijah'
>>> False or 'b'
'b'
>>> b = (1, 2, "K")
>>> b
(1, 2, 'K')
>>> False or b
(1, 2, 'K')
>>> 

请帮我弄清楚这里发生了什么事。在

根据文档:http://docs.python.org/2/library/stdtypes.html

除非另有说明,否则具有布尔结果的操作和内置函数始终返回0False表示false,1或{}表示真。(重要的例外:布尔运算or和{}总是返回其中一个操作数。)

根据LPTHW:http://learnpythonthehardway.org/book/ex28.html 为什么"test" and "test"返回“test”或1 and 1返回1而不是True? Python和许多类似的语言将一个操作数返回到它们的布尔表达式,而不仅仅是True或False。这意味着如果你做了False和1,你得到了第一个操作数(False),但是如果你做了True和1,你得到了第二个操作数(1)。玩一下这个。在


Tags: orandorgtest文本语言falsetrue
3条回答

这与Python中实现短路效应的方式有关。在

使用and(记住True and X = X),正确表达式的结果被推送到堆栈中,如果为false,则立即弹出,否则弹出第二个表达式:

>>> import dis
>>> 
>>> dis.dis(lambda : True and 0)
  1           0 LOAD_CONST               2 (True)
              3 JUMP_IF_FALSE_OR_POP     9
              6 LOAD_CONST               1 (0)
        >>    9 RETURN_VALUE
>>>
>>> True and 0
0
>>> 0 and True
0
>>>

微笑着说:

^{pr2}$

对于or,如果第一个表达式为真,则会立即弹出该表达式。如果不是,则弹出第二个表达式,现在结果实际上取决于第二个表达式。在

>>> dis.dis(lambda : 0 or False)
  1           0 LOAD_CONST               1 (0)
              3 JUMP_IF_TRUE_OR_POP      9
              6 LOAD_CONST               2 (False)
        >>    9 RETURN_VALUE
>>>
>>> True or 0
True
>>> 1 or False
1
>>> False or 1
1
>>>

微笑着说:

def exec_or(obj1, obj2):
    if bool(obj1) != True:
        return obj2
    return obj1

为了支持下面这样的习惯用法,人们希望and和{}求值为一个操作数(而不是总是求值为True或{}),以便支持以下习惯用法:

def foo(self):
    # currentfoo might be None, in which case return the default
    return self.currentfoo or self.defaultfoo()

def foobar(self):
    # foo() might return None, in which case return None
    foo = self.foo()
    return foo and foo.bar()

你当然可以质疑这些习语的价值,尤其是如果你不习惯的话。总是可以用显式的if编写等效代码。在

作为对它们不利的一点,它们留下了一些疑问,即是否可能并有意解释全部虚假价值,还是仅仅是评论中提到的错误价值(不允许其他虚假价值)。但是,对于使用值的真值的代码来说,这是正确的,该值可能不是True或{}。偶尔也会引起误解。在

我想你对医生说的有点困惑。看看这两个docs部分:Truth Value Testing and Boolean Operators。引用第一节最后一段:

Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated. (Important exception: the Boolean operations or and and always return one of their operands.)

如您所见,关于操作和内置函数,您是正确的,但是请参见重要异常部分,很好地说明了布尔运算符将返回其一个操作数。在

现在,他们能返回什么几乎不取决于操作员的短路逻辑。对于or运算符,它将返回表达式中的第一个truthy值,因为当它找到一个值时,整个表达式都是真的。如果每个操作数都是or将返回最后一个操作数,这意味着它迭代每个操作数都找不到一个真操作数。在

对于and运算符,如果表达式为true,则返回最后一个操作数;如果表达式为false,则返回第一个false操作数。您可以阅读有关Short Circuit Evaluation at the Wikipedia Page的更多信息。在

你的问题中有很多例子,我们来分析一下:

>>> False and 1  # return false (short circuited at first falsey value)
False
>>> True and 1   # return 1 (never short circuited and return the last truthy value)
1
>>> 1 and False  # return false (short circuited at first falsey value, in this case the last operand)
False
>>> 1 and True  # return True (never short circuited and return the last truthy value)
True
>>> True and 121  # return 121 (never short circuited and return the last truthy value)
121
>>> False or 1  # return 1 (since the first operand was falsey, or kept looking for a first truthy value which happened to be the last operator)
1
>>> False or 112  # return 112 for same reason as above
112
>>> False or "Khadijah"  # return "Khadijah" for same reason as above
'Khadijah'
>>> True and 'Khadijah'  # return "Khadijah" because same reason as second example
'Khadijah'

我认为这应该说明问题。为了帮助您进一步了解为什么这是有用的,请考虑以下示例:

你有一个随机生成名字的函数

^{pr2}$

你有一个变量,你不知道它是否已经分配了一个名称,而不是这样做:

if var is None:
    var = generate_name()

您可以使用oneliner:

var = var or generate_name()

由于None是一个假值,or将继续搜索并计算第二个操作数,即调用最终返回生成名称的函数。这是一个非常愚蠢的例子,我见过这种风格更好的用法(尽管在Python中没有)。我现在没有比这更好的例子了。你也可以看看这个问题,关于这个主题有很多有用的答案:Does Python support short-circuiting?

最后但并非最不重要的一点是,这与静态类型、duck类型、动态、解释、编译等任何语言无关。它只是一个语言特性,一个可能很有用的特性,这是非常常见的,因为我能想到的几乎所有编程语言都提供了这个特性。在

希望这有帮助!在

相关问题 更多 >