为什么“或”这样做?

时间:2013-03-14 18:35:20

标签: python syntax python-2.7

我在Python 2.7.3上尝试了很多不同的东西,我遇到了这段代码:

输入:

x = 4
y = 7
x or y

输出:

4

根据documentor是一个布尔运算。 or假设不仅仅会产生TrueFalse

所以,我用这段代码尝试了一些:

输入:

a = 3
b = 2
a or b

输出:

3

然后在这一点上,我假设代码将返回表达式的第一个参数。

为什么Python给了我这个输出? Python or操作背后真正发生了什么?

7 个答案:

答案 0 :(得分:4)

来自文档:

  

x或y:如果x为假,则为y,否则为x(1)

对于每个不等于零的整数,x or y将返回x

答案 1 :(得分:3)

georgesi的回答完美地回答了你提出的确切问题 - 但是你联系到的文档也是如此,因为他只是引用了那些文档。所以,大概你想要更多。

你可能会问两件事:

  1. 为什么是这样设计的Python,当我的本机直觉/喜欢的语言说or应该返回bool
  2. Python如何实现
  3. 由于你强调了“ Python or操作背后真正发生的事情”这个问题,我猜它是后者。

    请记住,Python有多种实现方式,只要符合参考文档设置的规范,他们就可以自由地实现他们想要的东西。但通常,当人们问“Python如何做到这一点?”他们的意思是“CPython实现如何做到这一点?”

    首先,让我们看看一些字节码:

    >>> def f():
    ...     return 1 or 2
    >>> import dis
    >>> dis.dis(f)
    2           0 LOAD_CONST               1 (1) 
                3 JUMP_IF_TRUE_OR_POP      9 
                6 LOAD_CONST               2 (2) 
          >>    9 RETURN_VALUE         
    

    这是什么意思?在Python-esque伪代码中,它是这样的:

    top = 1
    if top:
         goto 9
    else:
         del top
    top = 2
    label 9
    return top
    

    如果你想更好地理解(并且CPython是你关心的实现),你只需要知道CPython字节码解释器是一个简单的堆栈机器,并且该堆栈机器的代码在文件{{1 }}。因此,我们可以找到ceval.c代码here。 (JUMP_IF_TRUE_OR_POP操作码只是将常量值推送到堆栈上,以便LOAD_CONST可以找到它们。我认为我们真的不需要研究它以了解w = TOP()的工作原理。 )

    你可以看到它有点复杂。

    主要是因为它在调用与or等效的C-API之前通过检查if topif top == False来优化if top == True部分,并且因为它必须处理异常来自那个bool(top)电话。但它也在优化堆栈使用。如果不解释boolDISPATCH是如何工作的,那么很难过于精确,但基本的想法是,它避免从堆栈中弹出值只是为了将它们推回原点。

    但那是“Python FAST_DISPATCH操作背后真正发生了什么?”


    您还加粗了“or假设仅仅产生orTrue”那么,这会让我们回到问题1。 / p>

    首先,请记住,鸭子打字是Python的核心。 False应该会产生一些可以在任何重要的地方使用orTrue的东西。你应该特别写False而不是if foo:(或if foo == True:if foo is True:或其他),所以你不应该关心差异。< / p>

    其次,大约一半的语言都认同你的“布尔运算”应严格返回布尔类型的值,而其中一半不同意。即使是那些不是以鸭子打字为主的语言,比如C语言。那么,语言设计师如何决定呢?

    使if foo != False:运算符始终返回or的“C ++样式”避免了副本,允许编译器更好地执行静态类型,并为程序员提供更好的动态类型信息。前两个在Python中完全不相关,最后一个通常只在你编写依赖于类型而不是duck typing的代码时才有用,这通常被认为是unpythonic。

    使其返回第一个真值(或最后一个假值)的“C风格”使得实现稍微简单一些,并为程序员提供了三元bool的简写 - if表达。

    当Python没有三元else - if时,这是一个更简单的调用。如今,也许这是一个更近距离的电话 - 特别是因为有些人讨厌else作为a or b的简写,并认为它是非语音的。

    但历史已经存在于已有的一面;没有任何改变,除非有令人信服的理由,并且根据你的口味可能会出现相反方向的近距离通话并不是一个令人信服的理由。

答案 2 :(得分:2)

来自您提供的doc link

  

表达式x或y首先计算x;如果x为真,则其值为   回;否则,评估y并得到结果值   返回。

答案 3 :(得分:1)

请注意,or应该返回false的对象的唯一情况是两个操作数都是false。

考虑到这种行为,我们可以看到在第一个操作数为真的情况下,我们已经知道两个操作数都不是假的。这意味着无论第二个操作数是什么,整个表达式都应该计算为true。返回第一个操作数(即true)。

如果第一个操作数(我们称之为x)是 false x or y在逻辑上等同于y。如果y为真,则x和y都不为假,因此x or y为真。如果y为false,则x和y都为false,因此x or y为false。这就是如果x为false则返回y的原因。

这种方法称为短路评估,当x为假时,计算成本较低,因为不需要对y进行不必要的评估。

答案 4 :(得分:0)

Python中的or运算符将返回第一个值,如果它被认为是真,或者第二个值,如果第一个值为false,第二个值为true。如果两者都是假的,那么它将返回False。在这种情况下,4和3都是真值,因此返回它们。如果您改为使用0,则会看到使用的第二个值

x = 0
y = 3
x or y 

这将返回3

答案 5 :(得分:0)

这个问题已经回答了,但你仍然可能会问自己为什么这种行为会有意义。

这是一个简单的用例:

port = int(raw_input("Port number (default 5000): ") or 5000)

在这种情况下,or(和and)的行为非常有意义。另一个:

url_scheme = enable_https and 'https' or 'http'  # although this can be also expressed as:
url_scheme = 'https' if enable_https else 'http'
# but i personally prefer the above, because i can read it
# more easily due to the two possible values being closer together

答案 6 :(得分:-1)

这有点像速记if语句。我一直在JS编码中使用它。

您可以以同样的方式使用AND

var x = 0;

x && console.log('x is not truth-y');
x || console.log('x is false-y');

正如其他一些人已经说过的那样,&&||运算符评估左边的表达式然后,取决于我们是否是谈论&&||并且根据评估是真实还是假y,他们将停止或继续评估右侧的表达他们。