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 ] )
Sortie [3]:
[4365576160, 4365576160, 4365576160, 4365576160, 4365576160]
Pourquoi ont-ils tous la même adresse mémoire et comment puis-je en obtenir une copie a
?
python
string
python-2.7
d'habitude moi
la source
la source
d[ 'hello' ] = e
, oùe[ 'hi' ] = 'again'
. Pour générer un tel dictionnaire imbriqué, j'ai généré une
dictionnaire unique et je l'ai copié plusieurs fois. J'ai remarqué que la consommation de mémoire était très faible, ce qui a conduit à ma question ici. Maintenant, je comprends qu'aucune copie de chaîne n'a été créée, d'où la faible consommation de mémoire.b
être une version modifiée dea
sans modifiera
, laissez simplementb
être le résultat de n'importe quelle opération. par exemple desb = a[2:-1]
ensemblesb
à'll'
eta
reste »hello'
.Réponses:
Vous n'avez pas besoin de copier une chaîne Python. Ils sont immuables et le
copy
module renvoie toujours l'original dans de tels cas, comme le fontstr()
la tranche de chaîne entière, et concaténant avec une chaîne vide.De plus, votre
'hello'
chaîne est internée ( certaines chaînes le sont ). Python essaie délibérément de ne conserver qu'une seule copie, car cela accélère les recherches dans le dictionnaire.Une façon de contourner ce problème est de créer une nouvelle chaîne, puis de la découper dans le contenu d'origine:
>>> a = 'hello' >>> b = (a + '.')[:-1] >>> id(a), id(b) (4435312528, 4435312432)
Mais tout ce que vous faites maintenant, c'est perdre de la mémoire. Ce n'est pas comme si vous pouviez muter ces objets chaîne de quelque manière que ce soit, après tout.
Si tout ce que vous voulez savoir est la quantité de mémoire requise par un objet Python, utilisez
sys.getsizeof()
; il vous donne l'empreinte mémoire de n'importe quel objet Python.Pour les conteneurs, cela n'inclut pas le contenu; vous devrez récurer 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
id()
suivi pour prendre une empreinte mémoire réelle ou pour estimer une empreinte maximale si les objets n'ont pas été mis en cache et réutilisés.la source
b = ''.join(a)
.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)
la source
b = '{:s}'.format(a)
Je commence juste quelques manipulations de chaînes et j'ai 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 dissipé ma confusion, mais après y avoir réfléchi un peu, j'ai finalement "compris".
Tant que
a
,b
,c
,d
ete
ont la même valeur, ils font référence au même endroit. La mémoire est sauvegardée. Dès que la variable commence à avoir des valeurs différentes, elles commencent à avoir des références différentes. Mon expérience d'apprentissage est venue 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 source
La copie d'une chaîne peut être effectuée de deux manières, soit copier l'emplacement a = "a" b = a ou vous pouvez cloner ce qui signifie que b ne sera pas affecté lorsque a est modifié, ce qui est fait par a = 'a' b = a [:]
la source
Pour le dire différemment, "id ()" n'est pas ce qui vous importe. Vous voulez savoir si le nom de la variable peut être modifié sans nuire au 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, alors ce sont comme des variables de pointeur sauf que vous ne pouvez pas les dé-référencer pour modifier ce sur quoi elles pointent, mais id () vous dira où elles pointent actuellement.
Le problème pour les programmeurs python survient lorsque vous considérez des structures plus profondes comme des listes ou des dictionnaires:
>>> 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" dans le sens où vous pouvez changer la valeur de la clé 'a'. C'est pourquoi "y" doit être une copie et y ['a'] peut faire référence à autre chose.
la source