2011-07-25 14 views
5

Me pregunto si el intérprete de Python aplica una copia en la estrategia de escritura al hacer una copia profunda de los objetos mutables.¿Deepcopy usa copy-on-write?

Además, me gustaría saber si el deepcopy se lleva a cabo también en el objeto nonmutable (eso parecería extraño para mí, sin embargo)

Respuesta

5

No hace copia en escritura.

No hace una copia profunda en algunos tipos inmutables incorporadas, pero cualquier tipo "inmutables" definidos por el usuario será copiado de profundidad.

copy.py in the Python 2.7 standard library incluye este mensaje en su documentación:

Esta versión no copia tipos como módulo, clase, función, método, ni seguimiento de la pila, marco de pila, ni archivo, socket, ventana, ni matriz, ni ningún tipo similar.

copy trata los objetos inmutables como esto:

def _copy_immutable(x): 
    return x 
for t in (type(None), int, long, float, bool, str, tuple, 
      frozenset, type, xrange, types.ClassType, 
      types.BuiltinFunctionType, type(Ellipsis), 
      types.FunctionType, weakref.ref): 
    d[t] = _copy_immutable 
for name in ("ComplexType", "UnicodeType", "CodeType"): 
    t = getattr(types, name, None) 
    if t is not None: 
     d[t] = _copy_immutable 

deepcopy utiliza un esquema más complicado que es demasiado largo para copiar en ésta, la más, pero la esencia es la misma. Un punto interesante es que _deepcopy_tuple recorre sus elementos y no crea un objeto nuevo hasta que encuentra un elemento que se ha copiado.

for i in range(len(x)): 
    if x[i] is not y[i]: 
     y = tuple(y) 
     break 
else: 
    y = x 
+0

+1 por proporcionar ese enlace. Las líneas 41-43 indican claramente qué se copia y qué no. – Emiliano

+2

Parece ser más inteligente que eso: según mis pruebas, '(1, [2,3])' se copiará, pero '(1, (2,3))' no lo hará. Entonces, aparentemente, mira tanto los tipos contenidos como el contenedor. – interjay

+0

@happy Ha, ni siquiera me di cuenta. Debería incluir eso en la respuesta. –

4

No, no es cierto, sólo copia los objetos. Y también debe copiar objetos inmutables si hacen referencia a mutables.

+1

Ah, yo no estaba pensando en objetos inmutables que hacen referencia a los mutables. +1 por eso. Además, ¿eso significa que si emite una copia profunda para objetos de 2 módulos, incluso se copian los objetos de función (es decir, tengo 2 instancias de la misma función en la memoria)? – Emiliano

+1

@happy_emi: las funciones no se copian. Intente 'deepcopy (deepcopy) es deepcopy'. –

3

Veamos:

>>> import copy 
>>> x = [[1],[2],"abc"] 
>>> y = copy.deepcopy(x) 
>>> id(x[0]) 
4299612960 
>>> id(y[0]) 
4299541608 
>>> id(x[2]) 
4297774504 
>>> id(y[2]) 
4297774504 

Para el primer elemento de x y y, la copia se realiza y el objeto tiene una nueva identificación. El tercer elemento, una cadena inmutable, no se copia.