2017-02-21 4 views
9

J'essaie de comprendre comment fonctionne l'immutabilité en python. Puisque les chaînes de caractères sont immuables en python, je m'attendais à ce que l'identifiant change à chaque fois que j'effectue une opération de chaîne, mais cela ne fonctionne pas comme prévu. exemple: La dernière opération sur t ne modifie pas son identifiant. Des idées pourquoi?Immuabilité en Python

Screen shot of the operation

+0

En relation: [A propos de l'évolution de l'ID d'une chaîne Python immutable] (http://stackoverflow.com/questions/24245324/about-the-changing-id-of-a-python-immutable-string) – fredtantini

+1

Je déteste la façon dont cette optimisation viole la sémantique du langage Python. Selon la sémantique du langage, les valeurs de 't' avant et après le' + = 'devraient être des objets différents avec des durées de vie (à peine) superposées, il devrait donc être impossible pour eux de partager un' id'. – user2357112

Répondre

5

J'ai eu une rangée de pommes dans des cellules différentes [memory containing variables (I will not go to the bit level)], dont certains étaient vides [cells containing garbage/empty value].

J'en ai retiré un. C'était dans la cellule 3 [logical address = 3]. Je l'ai peint en bleu (après l'avoir cloné en utilisant le futur tech, pour la démonstration de l'immuabilité) [committed an operation on it, same could go for addition for integers]. J'ai regardé où le mettre, et bien que la cellule 4 soit libre, la cellule 3 l'était aussi (parce que la pomme "originale" n'est plus là)! Donc, je le mets dans la cellule 3 [and although we get a "new" apple, it has the same address].


En va de même pour votre t (notez que id est l'adresse mémoire de la variable dans CPython), mais étant donné que nous parlons de « chaînes de pommes » ici (cordes sont faites d'une séquence de caractères, nous avons de considérer la quantité d'espace que nous devons continuer la séquence, donc si j'avais ma mémoire ressemblant (_ représente des données de déchets arbitraires, «^» pour l'espace)

H e l l o _ _ _ _ _ B O O M 
^ string pointer points here 

et je voulais changer la chaîne à "Hello you", je pourrais envisager d'utiliser l'espace libre:

H e l l o^y o u _ B O O M 
^ string pointer points here 

Mais si je veux changer la chaîne à "Hello world!", je dois chercher un espace libre dans la longueur "Hello world!" ailleurs (nous aurions peut-être juste après "BOOM", ce qui est probable dans un environnement recueilli des ordures, regardez comment diffèrent vos ID):

H e l l o^y o u _ B O O M _ H e l l o^w o r l d ! _ G A R B A G E 
          ^string pointer points here 
+0

@ B.M. Le problème ici est la similitude avec l'internement. Ce que j'ai écrit est fondamentalement comme le commentaire de Martijn là-bas - "Python est libre de réutiliser les emplacements de mémoire." ' – Uriel

+0

@ B.M.Je ne comprends pas ce que vous voulez dire par "ça ne fonctionne pas comme ça". Ce que cette réponse décrit est que Python réutilise une adresse mémoire pour une nouvelle chaîne parce que la chaîne précédente a été récupérée. J'ai regardé le lien et je ne vois pas comment cela pourrait fournir une explication alternative au phénomène décrit dans la question. –

+0

Désolé, c'était trop direct. Je poste quelque chose pour expliquer ce que j'ai compris. Je pense que dans cet exemple, la pomme bleue n'est pas mise dans la cellule 3, vous laissez juste le vert ici et ajoutez de la peinture bleue à la fin de cell3. –

3

Les ID d'objets peuvent être réutilisés, tant que l'objet d'origine n'est plus présent. Ce n'est pas spécifique aux chaînes, mais à tous les types Python. Pour exemple le plus simple, vous pouvez examiner l'id simple object:

>>> print id(object()) 
140437485756544 
>>> print id(object()) 
140437485756544 

Cependant, si nous retenons une référence à l'objet précédent, l'identifiant ne sera pas réutilisé:

>>> a = object() 
>>> id(a) 
140437485756544 
>>> b = object() 
>>> id(b) 
140437485756560 

Vous pouvez reproduire le même comportement dans vos tests avec des chaînes en ajoutant les résultats intermédiaires (valeurs dans t) à une liste.

+0

Pourquoi dans les deux premiers cas de test d'ajouter "Test" à t l'ID a-t-il changé? Est-ce "aléatoire" ou est-ce que python a un moyen systématique d'allouer de la mémoire pour les chaînes dans ce cas? – PrestonM

+1

@PrestonM L'identifiant n'est pas garanti pour être réutilisé - quelque chose d'autre aurait pu prendre cet emplacement de mémoire (c'est ainsi que CPython implémente 'id') la première fois. Ce qui est garanti, c'est que l'identifiant d'un objet live ne change pas, et que deux objets distincts (et vivants) ne partagent pas le même identifiant. – user4815162342

+0

Cela prend tout son sens. Merci! – PrestonM