【发布时间】:2016-01-15 14:25:37
【问题描述】:
这是一个 Python 类,它实现了一些 magic methods:
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),即调用...
它不会导致方法中使用的> 调用它自己的方法。为什么?
【问题讨论】:
-
您希望
self.value在__setattr__中做什么?你永远不会在任何地方删除该属性,所以try..except..else总是转到else。 -
这不是重点。他只是在证明 __setattr__() 是递归的,但 __gt__() 不是。
-
@MartijnPieters 在初始化
A的实例时,您将得到name self.value未定义,因为该值在没有先存在的情况下无法设置。删除 try 块,尝试打印分配的值,你就会明白我的意思了。 -
__setattr__正在陷入死循环,是的,因为您明确调用它。 -
@MartijnPieters 是的,
a.inc()或类似的。
标签: python python-3.x recursion operator-overloading