为什么这些魔术方法不是递归的?

cat*_*cat 0 python recursion operator-overloading python-3.x

这是一个实现一些魔术方法的 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)
Run Code Online (Sandbox Code Playgroud)

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

>>> a.inc()
value changed its value from 0 to 1
1
Run Code Online (Sandbox Code Playgroud)

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

def __setattr__(self, name, value):
    self.__setattr__(name, value)
Run Code Online (Sandbox Code Playgroud)

现在尝试分配给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
Run Code Online (Sandbox Code Playgroud)

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

我的问题是,为什么这种递归性不适用于其他魔术方法?也就是说,当我调用 时obj.__gt__(otherval),它与说obj > otherval,哪个是对 的调用obj.__gt__(otherval),哪个是对……的调用相同,您明白了。

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

Mar*_*ers 5

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

如果您使用:

def __gt__(self, other):
    return self > other
Run Code Online (Sandbox Code Playgroud)

你也会陷入无限循环。