2013-11-01 152 views
5

我遇到了一些令人困惑的魔法比较方法。 假设我们有下面的类:Python魔法混淆

class MutNum(object): 
    def __init__ (self, val): 
     self.val = val 

    def setVal(self, newval): 
     self.val = newval 

    def __str__(self): 
     return str(self.val) 

    def __repr__(self): 
     return str(self.val) 

    # methods for comparison with a regular int or float: 
    def __eq__(self, other): 
     return self.val == other 

    def __gt__(self, other): 
     return self.val > other 

    def __lt__(self, other): 
     return self.val < other 

    def __ge__(self, other): 
     return self.__gt__(other) or self.__eq__(other) 

    def __le__(self, other): 
     return self.__lt__(other) or self.__eq__(other) 

类做的事情是应该做的,一个MutNum对象比较正规的整数或浮点数是没有问题的。然而,这是我不明白的地方,当魔法方法被给予两个MutNum对象时,它甚至会比较好。

a = MutNum(42) 
b = MutNum(3) 
print(a > b) # True 
print(a >= b) # True 
print(a < b) # False 
print(a <= b) # False 
print(a == b) # False 

为什么这样吗?谢谢。

+1

例如,可能会认为'__gt__'和'__lt__'与'__add__'和'__radd__'存在相同的关系。如果第一个不适用,Python会尝试使用颠倒的操作数的另一个。 – chepner

回答

4

它计算如下(使用repr般的符号,而不是指变量):

MutNum(42) > MutNum(3) 
=> MutNum(42).__gt__(MutNum(3)) 
=> MutNum(42).val > MutNum(3) 
=> 42 > MutNum(3) 

从那里,它只是你已经知道的作品INT-MutNum比较。

+0

@dust *你说*比较常规整数和浮点数与这个类的实例不是问题;-)'42> ...'不会再调用'MutNum .__ gt__',因为42不是'MutNum'。这种混淆是没有定义'__repr__'的原因之一,但添加了一些从它包装的数字中提取'MutNum'的东西。 – delnan

2

如果你扔在一些打印和/或sys.stderr.write的,我想你会看到发生了什么。 EG:

def __gt__(self, other): 
    sys.stderr.write('__gt__\n') 
    sys.stderr.write('{}\n'.format(type(other))) 
    sys.stderr.write('{} {}\n'.format(self.val, other)) 
    result = self.val > other 
    sys.stderr.write('result {}\n'.format(result)) 
    return result 

def __lt__(self, other): 
    sys.stderr.write('__lt__\n') 
    sys.stderr.write('{}\n'.format(type(other))) 
    sys.stderr.write('{} {}\n'.format(self.val, other)) 
    result = self.val < other 
    sys.stderr.write('result {}\n'.format(result)) 
    return result 

当您尝试self.val(一个int)比其他(一MutNum),蟒蛇实现它没有任何关系比较一个int到MutNum,并反转比较的秩序,将MutNum与int进行比较 - 这是您定义的内容。也就是说,一个单独的>比较正如您所期望的那样执行>,但它也在执行<。