pau*_*l23 3 python recursion private-members getattr
好吧,我有一个包含(相关部分)的课程:
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)
Run Code Online (Sandbox Code Playgroud)
基本上,我希望做的是将所有(部分)属性从“部分”传播到卫星中。即,如果我有10个零件的质量,卫星的质量就是这些零件的总和。-如果再添加一个具有储能功能的零件-我可以立即向上查找。-如果没有部件具有该属性,则该属性被认为是“不良” /“不存在”,并且会引发正常错误。
现在可以了,除了我这样做时:
s = satellite(None) #most simplistic one
ss = copy.copy(s)
Run Code Online (Sandbox Code Playgroud)
整个过程都出错了,从而在中给出了无限递归深度错误__getattr__()。
现在检查(pycharm的调试器)向我展示了它不断使用as参数迭代getattr:
item = _satellite__all_parts
然后在该行开始下一次迭代 for i in self.__all_parts:
现在,我对此感到震惊:__getattr_()据我所知,为什么__getattr__只对不存在的属性调用此行?-但是self.__all_parts显然__init__是在对象事件中声明的,那么为什么__getattr__还要激活?而且:为什么它不再理解对象了?
当然:我该如何进行这项工作?
编辑:只是为了清楚起见-这仅是由于复制而发生,并且(是由于martijn所致)是特定于复制行为的。链接的问题不处理复制案例。
copy.copy()尝试__setstate__在空实例上访问该属性,但尚未设置任何属性,因为__init__尚未调用(并且不会;copy.copy()将负责在其上设置新属性)。
寻找的__setstate__方法 copy.copy()是可选的,并且您的类确实没有这样的属性。因为它缺少,__getattr__被调用它,因为没有__all_parts属性又或者,该for i in self.__all_parts:行结束调用__getattr__一次。一遍又一遍。
诀窍是通过对其进行测试来尽早消除此循环。最好的方法是对所有以下划线开头的属性进行特殊处理:
if item.startswith('_'):
# bail out early
raise AttributeError(item)
Run Code Online (Sandbox Code Playgroud)