Eh bien, j'ai une classe qui se composent de (partie pertinente):récursion infinie pour __getattr __() - mais pourquoi est-il même appelé une fois?
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)
En fait ce que je veux faire est de propager tous (somme) les attributs des « parties » dans le satellite. C'est-à-dire que si j'ai 10 parties qui ont une masse, la masse du satellite est la somme de celles-ci. - Si j'ajoute ensuite une autre pièce qui a du stockage d'énergie - je peux immédiatement regarder ça aussi. - Si aucune partie n'a l'attribut, l'attribut est considéré comme "mauvais"/"inexistant" et il soulève l'erreur normale.
Maintenant cela fonctionne, sauf quand je fais:
s = satellite(None) #most simplistic one
ss = copy.copy(s)
L'ensemble des bugs chose, donnant une erreur de récursion infinie dans __getattr__()
.
Maintenant inspection (débogueur de PyCharm) me montre qu'il garde itérer le getattr avec comme argument:
item = _satellite__all_parts
Et il commence sa prochaine itération à la ligne for i in self.__all_parts:
Maintenant, je suis surpris par ceci: pourquoi cette ligne va-t-elle même à __getattr_()
- autant que je sache, __getattr__
est seulement appelé pour les attributs qui ne sont pas existants? - Mais self.__all_parts
est évidemment déclaré dans l'événement __init__
de l'objet, alors pourquoi __getattr__
est même activé? Et de plus: pourquoi ne comprend-il plus l'objet?
Et bien sûr: comment puis-je faire ce travail?
EDIT: juste pour la clarté - cela se produit UNIQUEMENT EN RAISON DE COPIE, et il est (était grâce à martijn) spécifique au comportement de copie. La question liée ne gère pas le cas de copie.
Je ne sais pas mais j'attendre qu'il doit faire avec le nom mutiler des éléments à double underscore-préfixés. Cela fonctionne-t-il si vous utilisez '_all_parts' à la place? –
Je ne suis pas sûr que l'implémentation '__getattr__' soit une bonne idée. Que faire si l'attribut n'ajoute pas bien? Je ne sais pas si c'est le cas dans votre scénario, mais il pourrait y avoir des attributs qui (a) ne peuvent pas être ajoutés, ou (b) où l'addition n'a pas de sens (par exemple, la vitesse de la sattelite n'est pas la somme des vitesses de ses parties). –
@DanielRoseman: Eh bien cela corrige pour l'appeler directement - mais toujours en utilisant "' copy.copy (t) '" donne la même erreur de récursivité. – paul23