2009-10-08 5 views
46

Je ne sais pas pourquoi les chaînes et les tuples ont été faits pour être immuables; Quels sont les avantages et les inconvénients de les rendre immuables?Pourquoi les chaînes et les tuples python sont-ils rendus immuables?

+1

autre que l'implémentation interne de l'interpréteur python, est-ce que cette conception a du sens pour l'écriture de programmes? (par exemple, cela facilitera-t-il le fait que les tuples et les chaînes soient mutables?) Si tel est le cas, quels seraient les exemples de choix de tuples ou de listes immuables? (ou peut-être, chaînes mutables vs chaînes python) – user186477

+3

Il existe tout un style de programmation appelé Programmation fonctionnelle où tout est immuable. http://en.wikipedia.org/wiki/Functional_programming –

+2

Python * DOES * possède des chaînes et des tuples mutables; ils sont épelés 'bytearray' et' list', respectivement. – SingleNegationElimination

Répondre

31

One est la performance: sachant qu'une chaîne est immuable, il est facile de étalez au moment de la construction - stockage fixe et immuable exigences. C'est aussi l'une des raisons pour la distinction entre tuples et listes. Cela permet également à l'implémentation de réutiliser en toute sécurité les objets chaîne . Par exemple, l'implémentation CPython utilise des objets pré-alloués pour des chaînes de caractères simples, et renvoie généralement la chaîne d'origine pour les opérations de chaîne, sans que cela modifie le contenu.

L'autre est que les chaînes en Python sont considérées comme "élémentaires" en tant que nombres . Aucune quantité d'activité ne changera la valeur 8 pour toute autre chose, et en Python, aucune quantité d'activité ne changera la chaîne "huit" en n'importe quoi d'autre.

http://effbot.org/pyfaq/why-are-python-strings-immutable.htm

2

pros: Performance

contre: vous ne pouvez pas changer mutables.

+6

les avantages: vous ne pouvez pas les changer –

10

Un gros avantage de les rendre immuables est qu'ils peuvent être utilisés comme clés dans un dictionnaire. Je suis sûr que les structures de données internes utilisées par les dictionnaires seraient complètement foirées si les clés étaient autorisées à changer.

+3

Buuuuut vous pouvez entrer par n'importe quelle instance d'objet créé par l'utilisateur, qui sont évidemment mutables. La "clé" est alors probablement juste l'adresse de la mémoire, et si les chaînes étaient mutables, vous pouvez toujours entrer une clé par leur adresse mémoire unique. – Triptych

+0

@Triptych qui ne serait pas ce que vous voulez pour les chaînes - vous voudriez qu'ils soient en valeur par clé, sinon les dictionnaires seraient de peu d'utilité ... – Hejazzman

+0

@Hejazzman ce n'est pas comme ça que les dicts python fonctionnent. La valeur de chaîne littérale n'est pas utilisée comme clé dict, mais un hachage de la chaîne est utilisé. Prouvez-le avec '' abc '.__ hash __() '. – Triptych

69

Imaginez une langue appelée FakeMutablePython, où vous pouvez modifier les chaînes en utilisant l'affectation de liste et telle (comme mystr[0] = 'a')

a = "abc" 

Cela crée une entrée dans la mémoire 0x1 adresse mémoire, contenant « abc », et identifiant a pointant vers lui.

Maintenant, supposons que vous faites ..

b = a 

Cela crée l'identifiant b et aussi des points à la même adresse mémoire de 0x1

Maintenant, si la chaîne était muable, et que vous changez b :

b[0] = 'z' 

Cela modifie le premier octet de la chaîne stockée à 0x1 à z .. Depuis l'identifiant a pointe vers ici pour, ainsi que la chaîne serait également modifié, donc ..

print a 
print b 

deux ..would sortie zbc

Cela pourrait faire pour certains, un comportement inattendu vraiment bizarre.Les clés de dictionnaire serait un bon exemple:

mykey = 'abc' 
mydict = { 
    mykey: 123, 
    'zbc': 321 
} 

anotherstring = mykey 
anotherstring[0] = 'z' 

Maintenant en FakeMutablePython, les choses deviennent assez bizarre - vous avez d'abord deux clés dans le dictionnaire, « abc » et « ZBC » .. Ensuite, vous modifiez le « abc "string (via l'identifiant anotherstring) à" zbc ", donc la dict a deux clés," zbc "et" zbc "...

Une solution à cette bizarrerie serait, chaque fois que vous affectez une chaîne à un identifiant (ou l'utiliser comme une clé dict), il copie la chaîne à 0x1 à 0x2.

Cela empêche ce qui précède, mais que faire si vous avez une chaîne qui nécessite 200 Mo de mémoire?

a = "really, really long string [...]" 
b = a 

Soudain, votre script occupe 400 Mo de mémoire? Ce n'est pas très bon.

Qu'en est-il si nous lui indiquons la même adresse mémoire, jusqu'à ce que nous l'ayons modifié? Copy on write. Le problème est, cela peut être assez compliqué à faire ..

C'est ici que l'immutabilité entre en jeu. Au lieu d'exiger la méthode .replace() pour copier la chaîne de la mémoire dans une nouvelle adresse, alors modifiez-la et retournez. il suffit de rendre toutes les chaînes immuables, et donc la fonction doit créer une nouvelle chaîne à renvoyer. Ceci explique le code suivant:

a = "abc" 
b = a.replace("a", "z") 

et il est prouvé par:

>>> a = 'abc' 
>>> b = a 
>>> id(a) == id(b) 
True 
>>> b = b.replace("a", "z") 
>>> id(a) == id(b) 
False 

(la fonction id() renvoie l'adresse mémoire de l'objet)

+2

+1 La meilleure réponse. Vraiment. – wassimans

+1

Meilleure explication que j'ai entendu! –

+0

donc si je dis a = "abc", b = "abcd" partagera-t-il abc? comme b [: 4] est un? – Dineshkumar

4

types Immuable sont conceptuellement beaucoup plus simples que ceux mutables . Par exemple, vous n'avez pas besoin de copier des constructeurs de copie ou de const-correction comme en C++. Plus les types sont immuables, plus le langage devient facile. Ainsi, les langages les plus simples sont les langages purement fonctionnels sans aucun état global (parce que le lambda-calcul est beaucoup plus facile que les machines de Turing, et tout aussi puissant), bien que beaucoup de gens ne semblent pas apprécier cela.

3

Perl a des chaînes mutables et semble fonctionner correctement. Ce qui précède semble être beaucoup de main agitant et de rationalisation pour une décision de conception arbitraire.

Ma réponse à la question de savoir pourquoi Python a des chaînes immuables, parce que le créateur de Python Guido van Rossum le voulait ainsi et il a maintenant des légions de fans qui défendront cette décision arbitraire jusqu'à leur dernier souffle. Vous pourriez poser une question similaire à savoir pourquoi Perl n'a pas de chaînes immuables et tout un groupe de personnes écrirait à quel point le concept même de chaînes immuables est horrible et pourquoi c'est la meilleure idée jamais (TM) que Perl ne ne les ai pas.

+1

Perl n'a pas vraiment de chaînes: il a des scalaires, qui peuvent se comporter comme des chaînes ou des nombres (plus d'un type de ce dernier). Si les scalaires étaient immuables, cela deviendrait purement fonctionnel. Les développeurs Perl et Perl du monde entier se suicideraient en leur assignant undef. –

Questions connexes