我有一个由(相关部分)组成的课程:
class satellite(object):
def __init__(self, orbit, payload=None, structural_mass=0, structural_price=0):
self.__all_parts = []
self.orbit = orbit
self.payload = payload
self.structural_mass = structural_mass
self.structural_price = structural_price
def __getattr__(self, item):
found = False
v = 0
for i in self.__all_parts:
t = getattr(i, item, None)
if t is not None:
v += t
found = True
if found:
return v
else:
raise AttributeError(item)
基本上我想做的是将所有(总和)属性从“部分”传播到卫星中。即如果我有10个具有质量的部分,卫星的质量就是那些的总和。 - 如果我然后添加另一个有能量存储的部分 - 我立刻也能看到它。 - 如果没有任何部分具有该属性,则该属性被视为“不良”/“不存在”,并且会引发正常错误。
现在这样可行,除非我这样做:
s = satellite(None) #most simplistic one
ss = copy.copy(s)
整个事情都是错误的,在__getattr__()
中给出了无限递归深度错误。
现在检查(pycharm的调试器)告诉我它继续使用as参数迭代getattr:
item = _satellite__all_parts
它在for i in self.__all_parts:
现在我对此感到吃惊:为什么这条线甚至会转到__getattr_()
- 据我所知__getattr__
只调用不存在的属性? - 但self.__all_parts
显然是在对象的__init__
事件中声明的,那么__getattr__
为什么会被激活呢?而且:为什么它不再理解这个对象了?
当然:我怎样才能做到这一点?
编辑:为了清楚起见 - 这只发生于复制,而且(由于martijn)特定于复制行为。链接的问题不处理复制案例。
答案 0 :(得分:4)
copy.copy()
尝试访问空实例上的__setstate__
属性,尚未设置任何属性,因为__init__
尚未被调用(并赢得了' t be; copy.copy()
负责在其上设置新属性。)
__setstate__
method copy.copy()
正在寻找是可选的,而您的类确实没有这样的属性。由于缺少__getattr__
,因为<{1}}属性 ,__all_parts
行最终会调用for i in self.__all_parts:
再次。一次又一次。
诀窍是通过测试来尽早切断这个循环。执行此操作的最佳方法是特殊情况下以下划线开头的所有属性:
__getattr__