代码之家  ›  专栏  ›  技术社区  ›  Nicholas Knight

在Python中,“只计算一次”对于链式比较意味着什么?

  •  19
  • Nicholas Knight  · 技术社区  · 15 年前

    一个朋友引起了我的注意,在我指出一个奇怪的地方后,我们都感到困惑。

    比如说Python的文档,并且至少从2.5.1开始就已经说过了(没有进一步检查:

    可以任意链接比较,例如x<y<=z等于x<y和y<=z、 除了y只计算一次(但在这两种情况下,当发现x<y为false时,z根本不计算)。

    我们的困惑在于“y只被评估一次”的含义。

    class Magic(object):
        def __init__(self, name, val):
            self.name = name
            self.val = val
        def __lt__(self, other):
            print("Magic: Called lt on {0}".format(self.name))
            if self.val < other.val:
                return True
            else:
                return False
        def __le__(self, other):
            print("Magic: Called le on {0}".format(self.name))
            if self.val <= other.val:
                return True
            else:
                return False
    

    我们可以得出这样的结果:

    >>> x = Magic("x", 0)
    >>> y = Magic("y", 5)
    >>> z = Magic("z", 10)
    >>> 
    >>> if x < y <= z:
    ...     print ("More magic.")
    ... 
    Magic: Called lt on x
    Magic: Called le on y
    More magic.
    >>> 
    

    这当然 就像“y”一样,在传统意义上是“评估”两次——当 x.__lt__(y) 调用并对其执行比较,并且在 y.__le__(z)

    考虑到这一点,Python文档说“y只计算一次”的确切含义是什么?

    2 回复  |  直到 10 年前
        1
  •  45
  •   Matt Anderson    15 年前

    “表达式” y 评估一次。即,在下面的表达式中,函数仅执行一次。

    >>> def five():
    ...    print 'returning 5'
    ...    return 5
    ... 
    >>> 1 < five() <= 5
    returning 5
    True
    

    与之相反:

    >>> 1 < five() and five() <= 5
    returning 5
    returning 5
    True
    
        2
  •  8
  •   Ants Aasma    15 年前

    class Foo(object):
        @property
        def complain(self):
            print("Evaluated!")
            return 2
    
    f = Foo()
    print(1 < f.complain < 3) # Prints evaluated once
    print(1 < f.complain and f.complain < 3)  # Prints evaluated twice