【问题标题】:Result of "a is a is a" comparison [duplicate]“a is a is a”比较的结果[重复]
【发布时间】:2018-01-18 07:21:05
【问题描述】:
A = 314

if A == A == A:
    print('True #1')

if A == A == 271:
    print('True #2')

lie = 0
if lie is lie is lie:
    print('no matter how white, how small,')
    print('how incorporating of a smidgeon')
    print('of truth there be in it.')

结果:

True #1
no matter how white, how small,
how incorporating of a smidgeon
of truth there be in it.

我知道在 if 语句中使用两个“=”和“is”是不正常的。但我想知道 Python 解释器如何解释 if 语句。

表达式lie is lie is lie是同时解释,还是短路方式?

【问题讨论】:

  • “同时”是什么意思?我猜它被解释为 0 < x < 3 只是使用不同的运算符(和操作数)。
  • 有趣的问题,但几乎可以肯定是一个骗子,之前在 SO 上必须问过运算符链接。
  • @tripleee 非“同时”,我的意思是“谎言就是谎言”返回“真”,然后“真就是谎言”,这可能会失败。根据回复,我理解为“谎言就是谎言,谎言就是谎言”。

标签: python


【解决方案1】:

您遇到的情况称为运算符链接

来自Comparisons上的文档:

比较可以任意链接,例如,x < y <= z 是 等价于x < y and y <= z,除了y 只计算一次 (但在这两种情况下,当发现 x < y 时,根本不会评估 z 假)。

强调我的。

所以,这意味着lie is lie is lie 被解释为(lie is lie) and (lie is lie),仅此而已。

更一般地说,a op b op c op d ... 的评估与a op b and b op c and c op d ... 相同,依此类推。表达式根据python的grammar rules解析。特别是;

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "!="
                   | "is" ["not"] | ["not"] "in"

【讨论】:

    【解决方案2】:

    这个问题已经有很多答案了,但是考虑将函数拆分为字节码:

    def f():
        lie = 0
        if lie is lie is lie:
            print('Lie')
    
    dis.dis(f)
    
      2           0 LOAD_CONST               1 (0)
                  2 STORE_FAST               0 (lie)
      3           4 LOAD_FAST                0 (lie)
                  6 LOAD_FAST                0 (lie)
                  8 DUP_TOP
                 10 ROT_THREE
                 12 COMPARE_OP               8 (is)
                 14 JUMP_IF_FALSE_OR_POP    22
                 16 LOAD_FAST                0 (lie)
                 18 COMPARE_OP               8 (is)
                 20 JUMP_FORWARD             4 (to 26)
            >>   22 ROT_TWO
                 24 POP_TOP
            >>   26 POP_JUMP_IF_FALSE       36
      4          28 LOAD_GLOBAL              0 (print)
                 30 LOAD_CONST               2 ('Lie')
                 32 CALL_FUNCTION            1
                 34 POP_TOP
            >>   36 LOAD_CONST               0 (None)
                 38 RETURN_VALUE
    

    这表明正在以线性方式检查所有lies 以查看它们是否匹配。如果一个失败,它应该中断/返回。

    要确认,请考虑:

    >lie is lie is lie is lie is lie 
    True
    >lie is not lie is lie is lie is lie is lie
    False
    >lie is lie is lie is lie is lie is not lie
    False
    

    【讨论】:

    • 我之前没有尝试过读取字节码。了解它的工作原理很有用。
    【解决方案3】:

    会被解释为:

    lie = 0
    if lie is lie and lie is lie:
        ...
    

    【讨论】:

    • ... 除了第三个lie 之外,不会再进行第二次评估。
    • 或者lie0 = lie1 = lie2 = 0; if lie0 is lie1 and lie1 is lie2 稍微澄清一下哪个是哪个。
    猜你喜欢
    • 1970-01-01
    • 2022-11-20
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 2022-12-26
    • 1970-01-01
    • 1970-01-01
    • 2022-12-02
    相关资源
    最近更新 更多