Ma compréhension était que les chaînes Python sont immuables.
J'ai essayé le code suivant:
a = "Dog"
b = "eats"
c = "treats"
print a, b, c
# Dog eats treats
print a + " " + b + " " + c
# Dog eats treats
print a
# Dog
a = a + " " + b + " " + c
print a
# Dog eats treats
# !!!
Python n'aurait-il pas dû empêcher l'affectation? Il me manque probablement quelque chose.
Une idée?
id()
fonction.a
aura un identifiant différent avant et après l'affectation, indiquant qu'il pointe vers différents objets. De même avec du code commeb = a
vous le trouvereza
etb
aurez le même identifiant, indiquant qu'ils référencent le même objet.Réponses:
Tout d'abord
a
pointé sur la chaîne "Dog". Ensuite, vous avez changé la variablea
pour pointer vers une nouvelle chaîne "Dog mange des friandises". Vous n'avez pas fait muter la chaîne "Dog". Les chaînes sont immuables, les variables peuvent pointer vers ce qu'elles veulent.la source
Les objets string eux-mêmes sont immuables.
La variable,
a
qui pointe vers la chaîne, est modifiable.Considérer:
la source
a.append(3)
n'est pas la même chose quea = a + 3
. Ce n'est même pasa += 3
(l'ajout inplace équivaut à.extend
, pas à.append
).+
se comporte de la même manière pour les listes et les chaînes - il concatène en crée une nouvelle copie et ne mute aucun des opérandes.append
fonction parce qu'elles sont immuables.La variable a pointe vers l'objet "Chien". Il est préférable de considérer la variable en Python comme une balise. Vous pouvez déplacer la balise vers différents objets, ce que vous avez fait lorsque vous êtes passé
a = "dog"
àa = "dog eats treats"
.Cependant, l'immuabilité fait référence à l'objet, pas à la balise.
Si vous avez essayé
a[1] = 'z'
de faire"dog"
dans"dzg"
, vous obtiendrez l'erreur:car les chaînes ne prennent pas en charge l'attribution d'éléments, elles sont donc immuables.
la source
Quelque chose n'est modifiable que lorsque nous sommes en mesure de modifier les valeurs contenues dans l'emplacement mémoire sans changer l'emplacement mémoire lui-même.
L'astuce est la suivante: si vous trouvez que l'emplacement mémoire avant et après le changement est le même, il est modifiable.
Par exemple, la liste est modifiable. Comment?
Une chaîne est immuable. Comment le prouver?
on a
Nous n'avons donc pas réussi à muter la chaîne. Cela signifie qu'une chaîne est immuable.
Lors de la réaffectation, vous modifiez la variable pour qu'elle pointe elle-même vers un nouvel emplacement. Ici, vous n'avez pas muté la chaîne, mais muté la variable elle-même. Voici ce que vous faites.
id
avant et après la réaffectation est différent, cela prouve donc que vous n'êtes pas en train de muter, mais que vous pointez la variable vers un nouvel emplacement. Ce qui n'est pas une mutation de cette chaîne, mais une mutation de cette variable.la source
Une variable n'est qu'une étiquette pointant vers un objet. L'objet est immuable, mais vous pouvez faire pointer l'étiquette vers un objet complètement différent si vous le souhaitez.
la source
Considérer:
Notez que l'emplacement de la mémoire hexadécimale n'a pas changé lorsque j'ai stocké la même valeur dans la variable deux fois. Cela a changé lorsque j'ai stocké une valeur différente. La chaîne est immuable. Pas à cause du fanatisme, mais parce que vous payez la pénalité de performance de créer un nouvel objet en mémoire. La variable
a
est juste une étiquette pointant vers cette adresse mémoire. Il peut être modifié pour pointer vers n'importe quoi.la source
L'instruction
a = a + " " + b + " " + c
peut être décomposée en fonction de pointeurs.a + " "
dit donnez-moi sur quelsa
points, ce qui ne peut pas être changé, et ajoutez-" "
moi à mon ensemble de travail actuel.Mémoire:
+ b
dit donnez-moi sur quelsb
points, ce qui ne peut pas être changé, et ajoutez-le à l'ensemble de travail actuel.Mémoire:
+ " " + c
dit ajouter" "
à l'ensemble actuel. Ensuite, donnez-moi sur quelsc
points, ce qui ne peut pas être changé, et ajoutez-le à l'ensemble de travail actuel. Mémoire:Enfin,
a =
dit définir mon pointeur pour qu'il pointe vers l'ensemble résultant.Mémoire:
"Dog"
est récupéré, car plus aucun pointeur ne se connecte à son morceau de mémoire. Nous n'avons jamais modifié la section mémoire"Dog"
dans laquelle résidait, c'est ce que l'on entend par immuable. Cependant, nous pouvons changer les étiquettes, le cas échéant, qui pointent vers cette section de mémoire.la source
la source
Il existe une différence entre les données et l'étiquette à laquelle elles sont associées. Par exemple quand vous faites
les données
"dog"
sont créées et placées sous l'étiquettea
. L'étiquette peut changer mais ce qui est en mémoire ne le sera pas. Les données"dog"
existeront toujours en mémoire (jusqu'à ce que le garbage collector les supprime) après que vous ayez faitDans votre programme
a
maintenant ^ pointe vers ^"cat"
mais la chaîne"dog"
n'a pas changé.la source
Les chaînes Python sont immuables. Cependant, ce
a
n'est pas une chaîne: c'est une variable avec une valeur de chaîne. Vous ne pouvez pas muter la chaîne, mais pouvez changer la valeur de la variable en une nouvelle chaîne.la source
Les variables peuvent pointer n'importe où elles le souhaitent. Une erreur sera générée si vous procédez comme suit:
la source
Les objets chaîne Python sont immuables. Exemple:
Dans cet exemple, nous pouvons voir que lorsque nous attribuons une valeur différente à un, cela ne modifie pas, un nouvel objet est créé.
Et il ne peut pas être modifié. Exemple:
Une erreur se produit.
la source
'mutable' signifie que nous pouvons changer le contenu de la chaîne, 'immutable' signifie que nous ne pouvons pas ajouter de chaîne supplémentaire.
la source
>>> a = 'dogs'
>>> a.replace('dogs', 'dogs eat treats')
'dogs eat treats'
>>> print a
'dogs'
Immuable, n'est-ce pas?!
La partie de changement de variable a déjà été discutée.
la source
replace()
méthode renvoie une nouvelle chaîne.Considérez cet ajout à votre exemple
L'une des explications les plus précises que j'ai trouvées dans un blog est:
Lien vers le blog: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/
la source
Ajouter un peu plus aux réponses mentionnées ci-dessus.
id
d'une variable change lors de la réaffectation.Ce qui signifie que nous avons muté la variable
a
pour qu'elle pointe vers une nouvelle chaîne. Il existe maintenant deuxstring
objets (str):'initial_string'
avecid
= 139982120425648et
'new_string'
avecid
= 139982120425776Considérez le code ci-dessous:
Maintenant,
b
pointe vers le'initial_string'
et a le mêmeid
que celuia
avant la réaffectation.Ainsi, le
'intial_string'
n'a pas été muté.la source
En résumé:
Pas immuable:
Immuable:
Il s'agit d'une erreur dans Python 3 car elle est immuable. Et pas une erreur dans Python 2 car clairement ce n'est pas immuable.
la source
La fonction intégrée
id()
renvoie l'identité d'un objet sous forme d'entier. Cet entier correspond généralement à l'emplacement de l'objet en mémoire.Initialement, 'a' est stocké dans l'emplacement mémoire 139831803293008, car l'objet chaîne est immuable en python si vous essayez de modifier et de réaffecter la référence sera supprimée et sera un pointeur vers un nouvel emplacement mémoire (139831803293120).
la source
la source
Cette image donne la réponse. Lisez-le s'il vous plaît.
la source
Nous concaténons simplement les deux valeurs de chaîne. Nous ne changeons jamais la valeur de (a). Tout à l'heure (a) représente un autre bloc de mémoire qui a la valeur "dogdog". Parce que dans le backend, une variable ne représente jamais deux blocs de mémoire en même temps. La valeur de (a) avant la concaténation était "dog". Mais après cela (a) représente le "chien de chien", car maintenant (a) dans le backend rep. le bloc qui a la valeur "dogdog". Et "chien" est rep. by (b) et "dog" n'est pas compté comme valeur de garbage jusqu'à ce que (b) représente le "dog".
La confusion est que nous représentons les blocs de mémoire (qui contiennent des données ou des informations) dans le backend avec le même nom de variable.
la source
Vous pouvez rendre un tableau numpy immuable et utiliser le premier élément:
puis:
ou
la source