代码之家  ›  专栏  ›  技术社区  ›  SingleNegationElimination

“foo<bar<baz”实际上调用了哪些方法?

  •  9
  • SingleNegationElimination  · 技术社区  · 14 年前

    在python中,我们可以说:

    if foo < bar < baz:
        do something.
    

    同样,我们可以重载比较运算符,例如:

    class Bar:
        def __lt__(self, other):
            do something else
    

    但是,这些区间比较的操作数类型的哪些方法实际上被调用?以上是否等同于

    if foo.__lt__(bar) and bar.__lt__(baz):
        do something.
    

    编辑:雷斯洛特,这里有一些输出有助于说明实际发生了什么。

    >>> class Bar:
        def __init__(self, name):
            self.name = name
            print('__init__', self.name)
        def __lt__(self, other):
            print('__lt__', self.name, other.name)
            return self.name < other.name
    
    >>> Bar('a') < Bar('b') < Bar('c')
    ('__init__', 'a')
    ('__init__', 'b')
    ('__lt__', 'a', 'b')
    ('__init__', 'c')
    ('__lt__', 'b', 'c')
    True
    >>> Bar('b') < Bar('a') < Bar('c')
    ('__init__', 'b')
    ('__init__', 'a')
    ('__lt__', 'b', 'a')
    False
    >>> 
    
    4 回复  |  直到 14 年前
        1
  •  4
  •   kikito    14 年前

    你是对的:

    class Bar:
        def __init__(self, name):
            self.name = name
        def __lt__(self, other):
            print('__lt__', self.name, other.name)
            return True
    
    a,b,c = Bar('a'), Bar('b'), Bar('c')
    
    a < b < c
    

    输出:

    ('__lt__', 'a', 'b')
    ('__lt__', 'b', 'c')
    True
    
        2
  •  12
  •   Mike Axiak    14 年前
    if foo < bar < baz:
    

    相当于

    if foo < bar and bar < baz:
    

    有一个重要的区别:如果bar是一个变异,它将被缓存。即。:

    if foo < bar() < baz:
    

    相当于

    tmp = bar()
    if foo < tmp and tmp < baz:
    

    但要回答你的问题,最终会是:

    if foo.__lt__(bar) and bar.__lt__(baz):
    
        3
  •  3
  •   hughdbrown    14 年前

    它使用对小于比较运算符的连续调用:

    >>> import dis
    >>> def foo(a,b,c):
    ...     return a < b < c
    ... 
    >>> dis.dis(foo)
      2           0 LOAD_FAST                0 (a)
                  3 LOAD_FAST                1 (b)
                  6 DUP_TOP             
                  7 ROT_THREE           
                  8 COMPARE_OP               0 (<)
                 11 JUMP_IF_FALSE            8 (to 22)
                 14 POP_TOP             
                 15 LOAD_FAST                2 (c)
                 18 COMPARE_OP               0 (<)
                 21 RETURN_VALUE        
            >>   22 ROT_TWO             
                 23 POP_TOP             
                 24 RETURN_VALUE        
    
        4
  •  1
  •   John Kugelman Michael Hodel    14 年前

    它调用特殊方法 __lt__() ,如果需要,它将调用 __nonzero__() 强迫 __中尉 一个布尔值。令人惊讶的是(至少对我来说),没有 __and__() 方法重写 and 接线员。

    下面是一个测试程序:

    #!/usr/bin/env python
    
    class Bar:
        def __init__(self, value):
            self.value = value
    
        def __lt__(self, other):
            print "%s.__lt__(%s)" % (self, other)
            return Bar("%s.__lt__(%s)" % (self, other))
    
        def __nonzero__(self):
            print "%s.__nonzero__()" % (self)
            return True
    
        def __str__(self):
            return self.value
    
    foo = Bar("foo")
    bar = Bar("bar")
    baz = Bar("baz")
    
    if foo < bar < baz:
        pass
    

    输出:

    foo.__lt__(bar)
    foo.__lt__(bar).__nonzero__()
    bar.__lt__(baz)
    bar.__lt__(baz).__nonzero__()