`foo < bar < baz` 实际调用了哪些方法?
在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.
编辑:关于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
>>>
4 个回答
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
13
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):
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