Je fais ça:
a = 'hello'
Et maintenant, je veux juste une copie indépendante de a
:
import copy
b = str(a)
c = a[:]
d = a + ''
e = copy.copy(a)
map( id, [ a,b,c,d,e ] )
Out [3]:
[4365576160, 4365576160, 4365576160, 4365576160, 4365576160]
Pourquoi ont-ils tous la même adresse mémoire et comment puis-je obtenir une copie de a
?
Vous n'avez pas besoin pour copier une chaîne Python. Ils sont immuables et le module copy
renvoie toujours l'original dans ces cas, de même que str()
, la tranche de chaîne entière et la concaténation avec une chaîne vide.
De plus, votre chaîne 'hello'
est interné ( certaines chaînes sont ). Python essaie délibérément de ne conserver qu'une copie, car cela accélère les recherches dans les dictionnaires.
Une façon de contourner ce problème consiste à créer une nouvelle chaîne, puis à la refaire dans le contenu d'origine:
>>> a = 'hello'
>>> b = (a + '.')[:-1]
>>> id(a), id(b)
(4435312528, 4435312432)
Mais tout ce que vous faites maintenant est une perte de mémoire. Ce n'est pas comme si vous pouviez transformer ces objets chaîne de quelque manière que ce soit, après tout.
Si vous ne souhaitez que connaître la quantité de mémoire requise par un objet Python, utilisez sys.getsizeof()
; il vous donne l'empreinte mémoire de tout objet Python.
Pour les conteneurs, cela ne comprend pas le contenu; vous auriez besoin de recurse dans chaque conteneur pour calculer une taille de mémoire totale:
>>> import sys
>>> a = 'hello'
>>> sys.getsizeof(a)
42
>>> b = {'foo': 'bar'}
>>> sys.getsizeof(b)
280
>>> sys.getsizeof(b) + sum(sys.getsizeof(k) + sys.getsizeof(v) for k, v in b.items())
360
Vous pouvez ensuite choisir d'utiliser le suivi id()
pour prendre une empreinte mémoire réelle ou pour estimer une empreinte maximum si les objets n'étaient pas mis en cache ni réutilisés.
Vous pouvez copier une chaîne en python via le formatage de chaîne:
>>> a = 'foo'
>>> b = '%s' % a
>>> id(a), id(b)
(140595444686784, 140595444726400)
Je viens de commencer quelques manipulations de chaîne et a trouvé cette question. J'essayais probablement de faire quelque chose comme l'Op, "d'habitude moi". Les réponses précédentes n'ont pas éclairci ma confusion, mais après avoir réfléchi un peu à la question, j'ai finalement "compris".
Tant que a
, b
, c
, d
et e
ont la même valeur, ils font référence au même endroit. La mémoire est enregistrée. Dès que la variable commence à avoir des valeurs différentes, elle commence à avoir des références différentes. Mon expérience d'apprentissage est issue de ce code:
import copy
a = 'hello'
b = str(a)
c = a[:]
d = a + ''
e = copy.copy(a)
print map( id, [ a,b,c,d,e ] )
print a, b, c, d, e
e = a + 'something'
a = 'goodbye'
print map( id, [ a,b,c,d,e ] )
print a, b, c, d, e
La sortie imprimée est:
[4538504992, 4538504992, 4538504992, 4538504992, 4538504992]
hello hello hello hello hello
[6113502048, 4538504992, 4538504992, 4538504992, 5570935808]
goodbye hello hello hello hello something
La copie d'une chaîne peut être effectuée de deux manières différentes: copiez l'emplacement a = "a" b = a ou vous pouvez cloner, ce qui signifie que b ne sera pas affecté par la modification de a qui est effectuée par a = 'a' b = a [:]
En d'autres termes, "id ()" ne vous intéresse pas. Vous voulez savoir si le nom de la variable peut être modifié sans endommager le nom de la variable source.
>>> a = 'hello'
>>> b = a[:]
>>> c = a
>>> b += ' world'
>>> c += ', bye'
>>> a
'hello'
>>> b
'hello world'
>>> c
'hello, bye'
Si vous êtes habitué à C, ce sont comme des variables de pointeur, sauf que vous ne pouvez pas les dé-référencer pour modifier leur pointage, mais id () vous indiquera où elles pointent actuellement.
Le problème pour les programmeurs python vient lorsque vous considérez des structures plus profondes telles que des listes ou des dict:
>>> o={'a': 10}
>>> x=o
>>> y=o.copy()
>>> x['a'] = 20
>>> y['a'] = 30
>>> o
{'a': 20}
>>> x
{'a': 20}
>>> y
{'a': 30}
Ici o et x font référence au même dict o ['a'] et x ['a'], et ce dict est "mutable" en ce sens que vous pouvez modifier la valeur de la clé 'a'. C'est pourquoi "y" doit être une copie et y ['a'] peut faire référence à autre chose.