在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.
编辑:re S.Lott,这是一些有助于说明实际情况的输出。
>>> 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
>>>
答案 0 :(得分:12)
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):
答案 1 :(得分:4)
你是对的:
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 :(得分:3)
它使用对小于比较运算符的连续调用:
>>> 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
答案 3 :(得分:1)
它调用特殊方法__lt__()
,如果需要,它将调用__nonzero__()
将__lt__()
的结果强制转换为布尔值。令人惊讶的是(至少对我来说),没有__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__()