2012-07-20 5 views
10

En p.35 de "Python Essential Reference" de David Beazley, primero establece:¿Tiene la asignación de otra variable a una cadena de realizar una copia o aumentar el número de referencia

Para los datos inmutables como las cadenas, la intérprete agresivamente comparte objetos entre diferentes partes del programa.

Sin embargo, más tarde en la misma página, afirma

Para los objetos inmutables como números y cadenas, esta asignación efectivamente crea una copia.

¿Pero no es esto una contradicción? Por un lado, él dice que son compartidos, pero luego dice que están copiados.

Respuesta

5

Es efectivamente crea una copia. No es en realidad crear una copia. La principal diferencia entre tener dos copias y tener dos nombres comparten el mismo valor es que, en este último caso, las modificaciones a través de un nombre afectan el valor del otro nombre. Si el valor no puede mutarse, esta diferencia desaparece, por lo que para los objetos inmutables hay poca consecuencia práctica de si el valor se copia o no.

Hay algunos casos de esquina donde se puede ver la diferencia entre las copias y diferentes objetos, incluso para los tipos inmutables (por ejemplo, mediante el uso de la función id o el operador is), pero éstas no son útiles para Python BuiltIn tipos inmutables (como cuerdas y números).

+1

Esto tiene muchas consecuencias prácticas. Considere la expresión comúnmente utilizada 'si la variable es None' ('None' es un objeto python inmutable incorporado y es importante si el objeto' es None' o simplemente se parece a 'None'). En principio, podrías hacer lo mismo con una cuerda que se ha apartado como especial. – mgilson

+0

En realidad, hay muy pocas consecuencias prácticas al usar 'si x es None' contra' si x == None'. Solo se diferenciarán en casos de esquina extraños (por ejemplo, donde 'x' es un objeto que define una extraña prueba' __eq__'). Hay incluso una menor necesidad práctica de usar 'is' en cadenas y números. No se recomienda confiar en 'is' para strings/ints especiales" apartados "porque esta" anulación "depende de la implementación. – BrenBarn

+1

Considere el caso común en el que usa 'if x is None:' para verificar si recibió un argumento de palabra clave. ¿Qué sucede si quiere aceptar 'None' como valor? Puedes hacer 'SENTINAL = ''; def foo (arg = SENTINAL); if (arg es SENTINAL): arg = [] 'por ejemplo. Esto no depende de la implementación. – mgilson

9

Una asignación en python nunca crea una copia (es técnicamente posible solo si la asignación para un miembro de la clase se redefine, por ejemplo, usando __setattr__, propiedades o descriptores).

Así que después de

a = foo() 
b = a 

todo lo que se volvió de foo no se ha copiado, y en su lugar se tienen dos variables a y b que apuntan al mismo objeto. No importa si el objeto es inmutable o no.

Con objetos inmutables Sin embargo, es difícil saber si este es el caso (porque no se puede mutar el objeto con una variable y comprobar si el cambio es visible usando la otra) por lo que son libres de pensar que, efectivamente, a y b no puede influenciarse el uno al otro.

Para algunos objetos inmutables también Python es libre de volver a utilizar objetos antiguos en lugar de crear otros nuevos y después de

a = x + y 
b = x + y 

donde tanto x y y son números (por lo que la suma es un número y es inmutable) puede ser que tanto a como b apuntarán al mismo objeto. Tenga en cuenta que no existe tal garantía ... también puede ser que, en su lugar, apunten a diferentes objetos con el mismo valor.

Lo importante a recordar es que Python nunca hace una copia a menos que se indique específicamente el uso, p. copy o deepcopy.Esto es muy importante con objetos mutables para evitar sorpresas.

Una construcción común que se puede ver es por ejemplo:

class Polygon: 
    def __init__(self, pts): 
     self.pts = pts[:] 
    ... 

En este caso self.pts = pts[:] se utiliza en lugar de self.pts = pts para hacer una copia de toda la gama de puntos para asegurarse de que la lista de puntos no va a cambiar inesperadamente si después de crear el objeto, los cambios se aplican a la lista que se pasó al constructor.

+0

Me gusta esta respuesta (+1) – mgilson

Cuestiones relacionadas