0
votes

Y a-t-il une façon recommandée d'assurer une immuabilité

Je suis en train d'observer le comportement suivant depuis que Python passe objet par référence? XXX

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? xxx


5 commentaires

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 . 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.


3 Réponses :


1
votes

J'observe le comportement suivant depuis que Python passe objet par référence?

pas vraiment. C'est une question subtile. Vous pouvez regarder Python - Comment passer une variable par référence? - Overflow de pile

Personnellement, je ne suis pas entièrement d'accord avec la réponse acceptée et vous vous recommandera Google appeler en partageant . Ensuite, vous pouvez prendre votre propre décision sur cette question subtile.

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?

Autant que je sache, il n'y a pas d'autre moyen meilleur, si vous n'utilisez pas le troisième colis.


0 commentaires

0
votes

Vous pouvez utiliser la méthode magique __ 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 à __ dict __ pour muter l'objet, et vous pouvez également dégeler l'objet en désétachant _frozen , et si la valeur de l'attribut elle-même est mutable, cela n'aide pas beaucoup ( x.things.append ('x') fonctionnerait pour une liste de choses ). xxx

sorties xxx


0 commentaires

0
votes

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 DataClass CODE> ou un ATTRAL FROZEN CODE> Classe

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 DataClass CODE> EXTENDES __ SETATTR __ CODE> __ DelatTR __ code> et remplace __ HASH __ CODE> P >

-> Utilisez une métaclasse. H3>

Les bonnes ressources incluent @Davidbeasleasley livres et des entretiens à Python. P>

-> 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,))

    ...


0 commentaires