web-dev-qa-db-fra.com

Les chaînes Python ne sont-elles pas immuables? Alors pourquoi a + "" + b fonctionne-t-il?

D'après ce que j'avais compris, 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? Je manque probablement quelque chose.

Une idée?

79
jason

La première a a indiqué la chaîne "Chien". Ensuite, vous avez modifié la variable a pour qu'elle pointe vers une nouvelle chaîne "Dog mange des friandises". Vous n'avez pas réellement muté la chaîne "Chien". Les chaînes sont immuables, les variables peuvent pointer vers ce qu'elles veulent.

144
Bort

Les objets de chaîne eux-mêmes sont immuables.

La variable, a, qui pointe vers la chaîne, est modifiable.

Considérer:

a = "Foo"
# a now points to "Foo"
b = a
# b points to the same "Foo" that a points to
a = a + a
# a points to the new string "FooFoo", but b still points to the old "Foo"

print a
print b
# Outputs:

# FooFoo
# Foo

# Observe that b hasn't changed, even though a has.
44

La variable a pointe sur l'objet "Chien". Il est préférable de penser à la variable en Python en tant que balise. Vous pouvez déplacer la balise vers différents objets, comme ce que vous avez fait lorsque vous avez modifié a = "dog" en a = "dog eats treats".

Cependant, l'immutabilité fait référence à l'objet, pas à la balise. 


Si vous avez essayé a[1] = 'z' pour transformer "dog" en "dzg", vous obtiendrez l'erreur suivante:

TypeError: 'str' object does not support item assignment" 

parce que les chaînes ne prennent pas en charge l’affectation d’éléments, elles sont donc immuables.

34
chrtan

Quelque chose est modifiable uniquement lorsque nous sommes en mesure de modifier les valeurs contenues dans l'emplacement de mémoire sans modifier l'emplacement de 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 mutable. Comment?

>> a = ['hello']
>> id(a)
139767295067632

# Now let's modify
#1
>> a[0] = "hello new"
>> a
['hello new']
Now that we have changed "a", let's see the location of a
>> id(a)
139767295067632
so it is the same as before. So we mutated a. So list is mutable.

Une ficelle est immuable. Comment pouvons-nous le prouver?

> a = "hello"
> a[0]
'h'
# Now let's modify it
> a[0] = 'n'
----------------------------------------------------------------------

on a

TypeError: l'objet 'str' ne prend pas en charge l'affectation d'élément

Nous avons donc échoué lors de la mutation de la chaîne. Cela signifie qu'une chaîne est immuable.

Lors de la réaffectation, vous modifiez la variable pour qu'elle pointe vers un nouvel emplacement. Ici, vous n'avez pas muté la chaîne, mais la variable elle-même. Ce qui suit est ce que vous faites.

>> a = "hello"
>> id(a)
139767308749440
>> a ="world"
>> id(a)
139767293625808

id avant et après la réaffectation est différent, cela prouve donc que vous ne effectuez pas de mutation, mais que vous pointez la variable vers le nouvel emplacement. Ce qui ne mute pas cette chaîne, mais mute cette variable.

11
Harish Kayarohanam

Une variable est simplement une étiquette pointant sur un objet. L'objet est immuable, mais vous pouvez faire que l'étiquette pointe sur un objet complètement différent si vous le souhaitez.

11
jcollado
l = [1,2,3]
print id(l)
l.append(4)
print id(l) #object l is the same

a = "dog"
print id(a)
a = "cat"
print id(a) #object a is a new object, previous one is deleted
6
user744629

Considérer:

>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='qwer'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x109198490>

Notez que l'emplacement de la mémoire hexadécimale n'a pas changé lorsque j'ai enregistré deux fois la même valeur dans la variable. Cela a changé lorsque j'ai stocké une valeur différente. La ficelle est immuable. Pas à cause du zèle, mais parce que vous payez la pénalité de performance de créer un nouvel objet en mémoire. La variable a est simplement une étiquette pointant vers cette adresse mémoire. Il peut être modifié pour indiquer n'importe quoi.

6
Bruno Bronosky

L'instruction a = a + " " + b + " " + c peut être décomposée en fonction des pointeurs.

a + " " dit que donnez-moi ce que a pointe sur, qui ne peut pas être changé, et ajoutez " " à mon ensemble de travail actuel.

mémoire:

working_set = "Dog "
a = "Dog" 
b = "eats"
c = "treats"

+ b dit donnez-moi ce que b pointe sur, ce qui ne peut pas être changé, et ajoutez-le au jeu de travail actuel.

mémoire:

working_set = "Dog eats"
a = "Dog" 
b = "eats"
c = "treats"

+ " " + c dit ajouter " " à l'ensemble actuel. Ensuite, donnez-moi ce que c pointe sur, ce qui ne peut pas être changé, et ajoutez-le au jeu de travail actuel. Mémoire:

working_set = "Dog eats treats"
a = "Dog" 
b = "eats"
c = "treats"

Enfin, a = dit que mon pointeur doit pointer sur le résultat.

mémoire:

a = "Dog eats treats"
b = "eats"
c = "treats"

"Dog" est récupéré, car aucun autre pointeur ne se connecte à son bloc de mémoire. Nous n’avons jamais modifié la section de mémoire dans laquelle "Dog" résidait, c’est ce que l’on entend par immuable. Cependant, nous pouvons changer les étiquettes, le cas échéant, pointant vers cette partie de la mémoire.

6
Spencer Rathbun

Il existe une différence entre les données et l'étiquette à laquelle elles sont associées. Par exemple quand tu fais 

a = "dog"

les données "dog" sont créées et placées sous l'étiquette a. L'étiquette peut changer mais ce qui est dans la mémoire ne changera pas. Le "dog" de données existera toujours en mémoire (jusqu'à ce que le récupérateur de mémoire le supprime) après l'avoir fait. 

a = "cat"

Dans votre programme a maintenant ^ pointe sur ^ "cat" mais la chaîne "dog" n'a pas changé.

5
mitch

Les chaînes de Python sont immuables. Cependant, a n'est pas une chaîne: il s'agit d'une variable avec une valeur de chaîne. Vous ne pouvez pas remplacer la chaîne, mais vous pouvez changer la valeur de la variable en une nouvelle chaîne.

3
Michael J. Barber

Les objets chaîne Python sont immuables . Exemple:

>>> a = 'tanim'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281536'
>>> a = 'ahmed'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281600'

Dans cet exemple, nous pouvons voir que lorsque nous affectons une valeur différente dans un paramètre, cela ne modifie pas. Un nouvel objet est créé.
Et il ne peut pas être modifié . Exemple:

  >>> a[0] = 'c'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    **TypeError**: 'str' object does not support item assignment

Une erreur survient.

2
Tanim_113

Les variables peuvent pointer où elles veulent ... Une erreur sera générée si vous procédez comme suit:

a = "dog"
print a                   #dog
a[1] = "g"                #ERROR!!!!!! STRINGS ARE IMMUTABLE
2
GuruJeya

Considérez cet ajout à votre exemple

 a = "Dog"
 b = "eats"
 c = "treats"
 print (a,b,c)
 #Dog eats treats
 d = a + " " + b + " " + c
 print (a)
 #Dog
 print (d)
 #Dog eats treats

L'une des explications les plus précises que j'ai trouvées dans un blog est la suivante: 

En Python, tout (ou presque) est un objet. Ce que nous appelons communément les "variables" en Python s’appelle plus proprement des noms. De même, "assignation" est vraiment la liaison d'un nom à un objet. Chaque liaison a une portée qui définit sa visibilité, généralement le bloc d'origine du nom.

Par exemple:

some_guy = 'Fred'
# ...
some_guy = 'George'

Lorsque nous dirons plus tard some_guy = 'George', l'objet chaîne contenant 'Fred' n'est pas affecté. Nous venons de changer la liaison du nom some_guy. Cependant, nous n'avons pas changé les objets chaîne "Fred" ou "George". En ce qui nous concerne, ils peuvent vivre indéfiniment.

Lien vers le blog: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/

1
7to4

'mutable' signifie que nous pouvons modifier le contenu de la chaîne, 'immuable' signifie que nous ne pouvons pas ajouter de chaîne supplémentaire.

click for photo proof

1
user10052573

Ajouter un peu plus aux réponses mentionnées ci-dessus.

id d’une variable change lors de la réaffectation.

>>> a = 'initial_string'
>>> id(a)
139982120425648
>>> a = 'new_string'
>>> id(a)
139982120425776

Ce qui signifie que nous avons muté la variable a pour qu'elle pointe vers une nouvelle chaîne. Maintenant, il existe deux string (str) objets:

'initial_string' avec id = 139982120425648

et

'new_string' avec id = 139982120425776

Considérons le code ci-dessous:

>>> b = 'intitial_string'
>>> id(b)
139982120425648

Maintenant, b pointe sur le 'initial_string' et a le même id que a avant la réaffectation.

Ainsi, le 'intial_string' n'a pas été muté.

1
Rahul Madiwale

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.

\>>a='dog'
\>>print(id(a))

139831803293008

\>>a=a+'cat'
\>>print(id(a))

139831803293120

Initialement, "a" est stocké dans l'emplacement de mémoire 139831803293008, car l'objet chaîne est immuable dans python si vous essayez de modifier et de réaffecter la référence, elle sera supprimée et constituera un pointeur vers un nouvel emplacement de mémoire (139831803293120). ).

0
learner5060

Vous pouvez rendre un tableau numpy immuable et utiliser le premier élément:

numpyarrayname[0] = "write once"

puis:

numpyarrayname.setflags(write=False)

ou

numpyarrayname.flags.writeable = False
0
PauluaP

Cette image donne la réponse. Lisez-le s'il vous plaît.

 enter image description here

0
Wen Qi

Résumant:

a = 3
b = a
a = 3+2
print b
# 5

Non immuable:

a = 'OOP'
b = a
a = 'p'+a
print b
# OOP

Immuable:

a = [1,2,3]
b = range(len(a))
for i in range(len(a)):
    b[i] = a[i]+1

C'est une erreur dans Python 3 car elle est immuable. Et pas une erreur dans Python 2 car ce n’est clairement pas immuable.

0
pjf