为什么这些神奇的方法不会递归?

时间:2016-01-15 14:25:37

标签: python python-3.x recursion operator-overloading

这是一个实现一些magic methods的Python类:

class A():
    def __init__(self, value):
        self.value = value

    def inc(self):
        self.value += 1
        return self.value

    def dec(self):
        self.value -= 1
        return self.value

    def __eq__(self, other):
        return self.value == other

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

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

    def __setattr__(self, name, value):
        try:
            self.value
        except:
            pass
        else:
            print(name, "changed its value from", self.value, "to", value)
        finally:
            super().__setattr__(name, value)

它实现了某些对象上定义的(虽然是冗余的)方法,并且允许比较和(在__setattr__情况下)赋值挂钩:

>>> a.inc()
value changed its value from 0 to 1
1

假设我们重新定义__setattr__以使其更简单:

def __setattr__(self, name, value):
    self.__setattr__(name, value)

现在尝试分配到self.value会让你一记耳光:

  File "<pyshell#50>", line 17, in __setattr__
    self.__setattr__(name, value)
  File "<pyshell#50>", line 17, in __setattr__
    self.__setattr__(name, value)
  File "<pyshell#50>", line 17, in __setattr__
    self.__setattr__(name, value)
  File "<pyshell#50>", line 17, in __setattr__
    self.__setattr__(name, value)
  File "<pyshell#50>", line 17, in __setattr__
    self.__setattr__(name, value)
RecursionError: maximum recursion depth exceeded

嗯,这是预期的。函数__setattr__是递归的;这就是为什么我们需要使用super()

我的问题是,为什么这种递归不适用于其他魔术方法;也就是说,当我拨打obj.__gt__(otherval)时,它就像说obj > otherval一样,这是对obj.__gt__(otherval)的调用,这是对...的调用...好吧,你得到它。

它不会导致方法中使用的>调用自己的方法。为什么呢?

1 个答案:

答案 0 :(得分:4)

您未在>上调用self。您在self.value上调用它,这是一个整数值(例如完全不同的类型)。

如果您使用:

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

你也会陷入无休止的循环中。