2010-11-29 33 views
1

Je comprends le concept de mutable v. Objets immuables en Python, pas de problème. Alors que la valeur intrinsèque de n'importe quel objet immuable ne peut pas être modifiée directement, n'importe quelle instance d'un objet immuable peut être rétablie avec des valeurs différentes. Ce que je voudrais faire est de construire une fonction interne sur une sous-classe de tuple qui peut, de façon contrôlée, réaffecter sa propre valeur. Cela pourrait être une fonctionnalité de base que je n'arrive pas à trouver et j'apprécierais toute aide. Par exemple, voici ce que j'aimerais pouvoir faire, mais cela ne marche évidemment pas.Objet tuple de sous-classe Python avec possibilité de réinstancier soi-même en interne

class myTuple(tuple): 
    def __new__(self): 
     initialValue = [1, 2, 3] 
     return super(myTuple, self).__new__(self, initialValue) 
    def resetMyself(self): 
     newValue = [4, 5, 6] 
     self = tuple(newValue) 

Avec les résultats suivants ...

>>> foo = myTuple() 
>>> print foo 
(1, 2, 3) 
>>> foo.resetMyself() 
>>> print foo 
(4, 5, 6) 

De la lecture d'un plus grand nombre de réponses aux questions de ce genre sur ce site, je sais que certains d'entre vous ont tendance à répondre « Pourquoi Voudrais-tu faire ça? mais sauvons l'espace de réponse avec des réponses plus directes, y compris peut-être «Vous ne pouvez pas le faire d'aucune façon, pas comment», si c'est vraiment le cas.

Merci beaucoup à tous!

EDIT, MERCI POUR LA RÉPONSE CI-DESSOUS, EST ICI CE QUE JE ... fini avec

class semiImmutableList(list): 
    def __setitem__(self, *args): 
     raise TypeError("'semiImmutableList' object doesn't support item assignment") 
    __setslice__ = __setitem__ 
    def __delitem__(self, *args): 
     raise TypeError("'semiImmutableList' object doesn't support item deletion") 
    __delslice__ = __delitem__ 
    def append(self, *args): 
     raise AttributeError("'semiImmutableList' object has no attribute 'append'") 
    def extend(self, *args): 
     raise AttributeError("'semiImmutableList' object has no attribute 'extend'") 
    def insert(self, *args): 
     raise AttributeError("'semiImmutableList' object has no attribute 'insert'") 
    def remove(self, *args): 
     raise AttributeError("'semiImmutableList' object has no attribute 'remove'") 
    def pop(self, *args): 
     raise AttributeError("'semiImmutableList' object has no attribute 'pop'") 
    def __init__(self): 
     x = [1, 2, 3] 
     super(semiImmutableList, self).__init__(x) 
    def resetMyself(self): 
     super(semiImmutableList,self).append(5) 

Toute amélioration/ajustements à ce qui précède que vous pouvez voir s'il vous plaît poster. On dirait que la duplication des hausses d'AttributeError pourrait être combinée?

+0

Vous ne savez pas exactement ce que vous entendez par "toute instance d'un objet immuable peut être réinstancée avec des valeurs différentes". De nouveaux objets avec des valeurs différentes peuvent être créés et liés au même nom, mais un objet immuable ne peut pas être changé (d'où le terme). Un objet immuable "réinstancié" est un objet différent. – martineau

+0

Oui, un phrasé pauvre de ma part. Si x = (1, 2, 3), il ne peut jamais être changé, mais x peut devenir un autre objet, y compris un autre tuple avec une réaffectation simple ... x = (3, 4, 5). x est x mais le premier objet tuple x référencé est simplement parti, non modifié. – sansjoe

+0

def resetMyself (auto): super (semiImmutableList, self) .append (5): pourquoi utiliser super au lieu de passer soi-même à une liste? Je me demandais si votre exemple d'échec était parce que vous n'êtes pas retourné soi-même, en quelque sorte (nous avons eu une explication sur la façon de le faire, pas pourquoi cela ne fonctionne pas) –

Répondre

1

Assez facile, tout ce que vous avez à faire est d'envelopper une liste.

class ImmutableList(object): 
    def __init__(self, *args): 
     self.__values = args; # internally we store the values in a list 

    # make imuList[0] = 2 raise an error, just like a tuple would 
    def __setitem__(self, index, value): 
     raise TypeError('ImmutableList does not support item assignment') 

    # del imuList[0] should also raise 
    def __delitem__(self, index, value): 
     raise TypeError('ImmutableList does not support item deletion')** 

    # make our imuList indexable, also catch the normal index error and raise one 
    # that tells that this is an immutable list, will make it easier to debug :) 
    def __getitem__(self, index): 
     try: 
      return self.__values[index] 

     except IndexError: 
      raise IndexError('ImmutableList index out of range') 

    # the usual stuff 
    def __repr__(self): 
     return repr(self.__values) 

    def __str__(self): 
     return str(self.__values) 

# create a new imulist 
e = ImmutableList(1, 2, 3, 4) 

# works! 
print e[0] 

# raises an error 
e[0] = 5 

# raises another error 
print e[9] 

Maintenant, tout ce que vous devez faire est de modifier self._values dans la classe. Un dernier conseil, il est toujours possible de jouer avec self._values de l'extérieur, que parce que Python ne supporte pas private members.

Vous pouvez prendre d'autres mesures contre la manipulation de __values en le sous-classant directement dans la liste, mais cela demande plus de travail et on peut encore bidouiller avec les valeurs en utilisant list.__setitem__(imListInstance, 0, 5) et autres.

+0

Merci pour cette assistance! Avec cela et quelques autres sources sur le net, je me suis retrouvé avec le code ajouté comme un edit à la question qui vient sous-classe la liste et éteint (espérons-le) toute l'immuabilité intégrée. – sansjoe

2

Si vous voulez un tuple modifiable, utilisez une liste.

modifier:

essayer cette

class FrankenList(object): 
    def __init__(self, init=None): 
     self.__data = init or [] 

    def __getitem__(self, key): 
     return self.__data[key] 

    def __repr__(self): 
     return repr(self.__data) 

    def __str__(self): 
     return str(self.__data) 
+0

Je veux l'immutabilité externe.Puis-je rendre mon instance de liste publiquement immuable tout en conservant la possibilité de me modifier en interne? – sansjoe

+0

Tant que votre n'a pas fourni de méthodes comme ____setitem____, ____delitem____ etc. – Kabie

+0

comme, par exemple, le code ci-dessus –