Je suis en train d'observer le comportement suivant depuis que Python passe objet par référence? J'ai trouvé copie.deepcopy () à l'objet de Copopy pour empêcher la modification de l'objet transmis. Y a-t-il d'autres recommandations? p>
3 Réponses :
J'observe le comportement suivant depuis que Python passe objet par référence? P> blockQuote>
pas vraiment. C'est une question subtile. Vous pouvez regarder Python - Comment passer une variable par référence? - Overflow de pile p>
Personnellement, je ne suis pas entièrement d'accord avec la réponse acceptée et vous vous recommandera Google
appeler en partageant code>. Ensuite, vous pouvez prendre votre propre décision sur cette question subtile. P>J'ai trouvé copie.deepcopy () sur l'objet de Copopy pour empêcher la modification de l'objet transmis. Y a-t-il d'autres recommandations? P> blockQuote>
Autant que je sache, il n'y a pas d'autre moyen meilleur, si vous n'utilisez pas le troisième colis. p>
Vous pouvez utiliser la méthode magique code> __ code> pour implémenter une classe de base qui vous permet de "geler" un objet après avoir terminé avec elle.
Ce n'est pas la preuve de balle; Vous pouvez toujours accéder à sorties p> __ dict __ code> pour muter l'objet, et vous pouvez également dégeler l'objet en désétachant _frozen code>, et si la valeur de l'attribut elle-même est mutable, cela n'aide pas beaucoup ( x.things.append ('x') code> fonctionnerait pour une liste de choses code>). p>
Il n'y a pas vraiment de 100% de voie étanche, mais vous pouvez rendre difficile la mutation par inadvertance d'un objet que vous souhaitez congelez. La voie recommandée pour la plupart des gens est probablement d'utiliser un dans son Talk sur Dataclasses (2018), @raymonHettinger, mentionne trois approches: une solution est avec une métaclass forte>, une autre, comme dans le Fractions Module est de donner des attributs A Lecture seule propriété forte>; Le Module Les bonnes ressources incluent @Davidbeasleasley livres et des entretiens à Python. P> DataClass CODE> ou un ATTRAL FROZEN CODE> Classe DataClass CODE> __ SETATTR __ CODE> __ DelatTR __ code> et remplace __ HASH __ CODE> P > -> Utilisez une métaclasse. H3>
-> Donnez des attributs une propriété en lecture seule h3>
class FrozenObject:
...
def __setattr__(self, name, value):
if type(self) is cls or name in (tuple of attributes to freeze,):
raise FrozenInstanceError(f'cannot assign to field {name}')
super(cls, self).__setattr__(name, value)
def __delattr__(self, name):
if type(self) is cls or name in (tuple of attributes to freeze,):
raise FrozenInstanceError(f'cannot delete field {name}')
super(cls, self).__delattr__(name, value)
def __hash__(self):
return hash((tuple of attributes to freeze,))
...
Dans ce cas particulier, vous pouvez remplacer le Setter pour le nom pour renvoyer une copie de l'objet avec la nouvelle valeur du nom d'attribut. En général, la manière de garantir l'immutabilité consiste à garantir qu'il n'y ait aucune méthode de mutation des données dans la classe.
@RDAS Le problème que j'ai est que je dois muter plusieurs propriétés afin de remplacer les setters me donnera un nouvel objet à chaque fois
Que diriez-vous de définir tous les attributs pendant la construction? Remplacer les Setteurs ne devrait pas être un problème alors ...
La question est la raison pour laquelle vous devriez vouloir faire cela? Ce n'est pas un moyen «pythonic» et vous risquez de casser beaucoup de choses (par exemple, moquez). Si vous voulez faire quelque chose de le rendre lisez-le à réadonner via
@property code>. Cela suffit pour empêcher la mutation accidentelle et permet toujours à tous, qui souhaitent vraiment changer pour les laisser passer.Si vous devez muter des propriétés, vous ne voulez pas assurer l'immuabilité. La recommandation ici vous maintient les exigences cohérentes.