Hago esto:
a = 'hello'
Y ahora solo quiero una copia independiente de a
:
import copy
b = str(a)
c = a[:]
d = a + ''
e = copy.copy(a)
map( id, [ a,b,c,d,e ] )
Fuera [3]:
[4365576160, 4365576160, 4365576160, 4365576160, 4365576160]
¿Por qué todos tienen la misma dirección de memoria y cómo puedo obtener una copia a
?
python
string
python-2.7
yo habitual
fuente
fuente
d[ 'hello' ] = e
, dondee[ 'hi' ] = 'again'
. Para generar un diccionario anidado, generé un soloe
diccionario y lo copié varias veces. Noté que el consumo de memoria era muy bajo, lo que llevó a mi pregunta aquí. Ahora entiendo que no se crearon copias de cadena, de ahí el bajo consumo de memoria.b
ser una versión modificada dea
sin modificara
, deja queb
sea el resultado de cualquier operación. por ejemplo, seb = a[2:-1]
estableceb
en'll'
ya
permanece 'hello'
.Respuestas:
No necesitas copiar una cadena de Python. Son inmutables, y el
copy
módulo siempre devuelve el original en tales casos, al igual questr()
el segmento de cadena completo y se concatena con una cadena vacía.Además, tu
'hello'
cuerda está internada ( ciertas cuerdas están ). Python intenta deliberadamente mantener una sola copia, ya que eso hace que las búsquedas en el diccionario sean más rápidas.Una forma de solucionar esto es crear una nueva cadena y luego volver a cortar esa cadena al contenido original:
>>> a = 'hello' >>> b = (a + '.')[:-1] >>> id(a), id(b) (4435312528, 4435312432)
Pero todo lo que estás haciendo ahora es desperdiciar memoria. Después de todo, no es como si pudiera mutar estos objetos de cadena de alguna manera.
Si todo lo que quería saber es cuánta memoria requiere un objeto Python, use
sys.getsizeof()
; le da la huella de memoria de cualquier objeto de Python.Para contenedores, esto no incluye el contenido; tendría que recurrir a cada contenedor para calcular un tamaño total de memoria:
>>> 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
Luego, puede optar por utilizar el
id()
seguimiento para tomar una huella de memoria real o para estimar una huella máxima si los objetos no se almacenaron en caché ni se reutilizaron.fuente
b = ''.join(a)
.Puede copiar una cadena en Python a través del formato de cadena:
>>> a = 'foo' >>> b = '%s' % a >>> id(a), id(b) (140595444686784, 140595444726400)
fuente
b = '{:s}'.format(a)
Acabo de comenzar algunas manipulaciones de cadenas y encontré esta pregunta. Probablemente estaba tratando de hacer algo como el OP, "yo habitual". Las respuestas anteriores no aclararon mi confusión, pero después de pensar un poco al respecto finalmente "lo entendí".
Mientras
a
,b
,c
,d
, ye
tienen el mismo valor, los que hacen referencia al mismo lugar. La memoria está guardada. Tan pronto como la variable comienza a tener diferentes valores, comienzan a tener diferentes referencias. Mi experiencia de aprendizaje provino de este código: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 salida impresa es:
[4538504992, 4538504992, 4538504992, 4538504992, 4538504992] hello hello hello hello hello [6113502048, 4538504992, 4538504992, 4538504992, 5570935808] goodbye hello hello hello hello something
fuente
La copia de una cadena se puede hacer de dos maneras, ya sea copiando la ubicación a = "a" b = a o puede clonar, lo que significa que b no se verá afectado cuando se cambie a, lo cual se hace mediante a = 'a' b = a [:]
fuente
Para decirlo de otra manera, "id ()" no es lo que te importa. Desea saber si el nombre de la variable se puede modificar sin dañar el nombre de la variable de origen.
>>> a = 'hello' >>> b = a[:] >>> c = a >>> b += ' world' >>> c += ', bye' >>> a 'hello' >>> b 'hello world' >>> c 'hello, bye'
Si está acostumbrado a C, entonces estas son como variables de puntero, excepto que no puede des-referenciarlas para modificar a qué apuntan, pero id () le dirá dónde apuntan actualmente.
El problema para los programadores de Python surge cuando considera estructuras más profundas como listas o dictados:
>>> o={'a': 10} >>> x=o >>> y=o.copy() >>> x['a'] = 20 >>> y['a'] = 30 >>> o {'a': 20} >>> x {'a': 20} >>> y {'a': 30}
Aquí oyx se refieren al mismo dict o ['a'] yx ['a'], y ese dict es "mutable" en el sentido de que puede cambiar el valor de la clave 'a'. Es por eso que "y" debe ser una copia y y ['a'] puede referirse a otra cosa.
fuente