Well I have a class that consist of (relevant part):
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)
Basically what I wish to do is propagate all (sum of) attributes from the "parts" into the satellite. Ie if I have 10 parts that have mass, the mass of the satellite is the sum of those. - If I then add another part that has energy storage - I immediatelly can look that also up. - If no part has the attribute, the attribute is considered to be "bad"/"unexistent" and it raises the normal error.
Now this works, except when I do:
s = satellite(None) #most simplistic one
ss = copy.copy(s)
The whole thing bugs out, giving an infinite recursion depth error in __getattr__()
.
Now inspection (pycharm's debugger) shows me that it keeps iterating the getattr with as argument:
item = _satellite__all_parts
And it starts its next iteration at the line for i in self.__all_parts:
Now I'm startled by this: why is this line even going to __getattr_()
- as far as I know __getattr__
is only called for attributes that aren't existing right? - But self.__all_parts
is obviously declared in the __init__
event of the object, so why is __getattr__
even activated? And furthermore: why does it not understand the object anymore?
And of course: how can I make this work?
EDIT: just for clarity - this occurs ONLY DUE TO COPY, and it is (was thanks to martijn) specific to the copying behaviour. The linked question doesn't handle the copy case.