2012-06-27 24 views
33

En el códigoPython asignación de referencia variable

y = 7 
x = y  
x = 8 

Ahora, y será de 7 x y habrá 8. Pero en realidad quiere cambiar y. ¿Puedo asignar la referencia de y y hacer eso?

Por ejemplo, en C++ la misma cosa se puede lograr como,

int y = 8; 
int &x = y; 
x = 9; 

Ahora ambos Y & x habrá 9

Respuesta

44

No, no se puede. Como señala otra respuesta, puede (¿ab?) Usar aliasing de objetos mutables para lograr un efecto similar. Sin embargo, eso no es lo mismo que las referencias de C++, y quiero explicar lo que realmente sucede para evitar cualquier concepto erróneo.

Verá, en C++ (y en otros idiomas), una variable (y campos de objetos, y entradas en colecciones, etc.) es una ubicación de almacenamiento y escribe un valor (por ejemplo, un entero, un objeto o un puntero) a esa ubicación. En este modelo, las referencias son un alias para una ubicación de almacenamiento (de cualquier tipo): cuando asigna una variable que no es de referencia, copia un valor (incluso si solo es un puntero, sigue siendo un valor) en la ubicación de almacenamiento; cuando asigna a una referencia, copia en un lugar de almacenamiento en otro lugar. Tenga en cuenta que no puede cambiar una referencia en sí misma; una vez que está enlazada (y tiene que hacerlo tan pronto como la cree), todas las asignaciones a la misma alteran no la referencia, sino lo que sea que se haga referencia a ella.

En Python (y en otros idiomas), una variable (y campos de objetos, y entradas en colecciones, etc.) es solo un nombre. Los valores son en algún lugar else (por ejemplo, salpicado todo el montón), y una variable se refiere (no en el sentido de referencias de C++, más como un puntero menos la aritmética del puntero) a un valor. Varios nombres pueden referirse al mismo valor (que generalmente es algo bueno). Python (y otros idiomas) llama a lo que sea necesario para referirse a un valor de referencia, a pesar de no estar relacionado con cosas como referencias de C++ y referencias pasadas. Asignar a una variable (o campo de objeto, o ...) simplemente lo hace referirse a otro valor.El modelo completo de ubicaciones de almacenamiento no se aplica a Python, el programador nunca maneja ubicaciones de almacenamiento para valores. Todo lo que almacena y baraja son referencias de Python, y esos no son valores en Python, por lo que no pueden ser el objetivo de otras referencias de Python.

Todo esto es independiente de la mutabilidad del valor; es lo mismo para los datos y las listas, por ejemplo. No puede tomar una variable que haga referencia a ninguno de los dos y sobrescribir el objeto al que apunta. Solo puede decirle al objeto que modifique partes de sí mismo, por ejemplo, cambie alguna referencia que contenga.

¿Es este un modelo más restrictivo? Tal vez, pero es lo suficientemente potente la mayor parte del tiempo. Y cuando no lo es, puede evitarlo, ya sea con una clase personalizada como la que se muestra a continuación, o (equivalente, pero menos obvio) una colección de elementos individuales.

class Reference: 
    def __init__(self, val): 
     self._value = val # just refers to val, no copy 

    def get(self): 
     return self._value 

    def set(self, val): 
     self._value = val 

Eso todavía no se le permitirá poner un alias para un campo variable u objeto "regular", pero puede tener múltiples variables referidas a la misma Reference objeto (ídem para la alternativa-Singleton-colección mutable). Solo debe tener cuidado de usar siempre .get()/.set() (o [0]).

+2

Buena explicación, +1 para aclarar que no tiene nada que ver con la mutabilidad. –

11

No, Python no tiene esta característica.

Si tuviera una lista (o cualquier otro objeto mutable) que podría hacer lo que quiere mediante la mutación del objeto que tanto x como y están obligados a:

>>> x = [7] 
>>> y = x 
>>> y[0] = 8 
>>> print x 
[8] 

ver su funcionamiento en línea: ideone

+1

Aunque esto es realmente útil, hay una desventaja más o menos grande en esta "mutación" de un único valor numérico simple. Convertir el número entero en una lista con un solo elemento requiere poco más de 3 veces el espacio de memoria que normalmente necesitará. Ejemplo (Usaré sys.getsizeof (...) para ilustrar la diferencia de tamaño): x = 1 -> sys.getsizeof (x) -> darnos 14 -> x = [1] -> sys.getsizeof (x) -> nos da 36 – rbaleksandar

5

Debe usar un objeto mutable para esto.

en Python x & y son sólo referencias a objetos así y = 7 significa que Y puntos en el objeto 7. x=y significa x también puntos para 7, pero como 7 es inmutable por lo que cambiar el valor de x simplemente cambia el objeto 7 y y todavía queda apuntando a 7.

>>> y = [7] 
>>> x = y 
>>> x[0] = 8 # here you're changing [7] not x or y, x & y are just references to [7] 
>>> y 
[8] 
+0

que quería señalar que y permanece sin cambios incluso después de cambiar x, pero eso no es lo que escribió aquí. Por favor aclara –

1

Como alternativa, podría utilizar un contenedor auto elaborado.

class Value(object): 
    def __init__(self, value): self.value = value 

y = Value(7) 
x = y 
x.value = 8 
print y.value 

ideone

Cuestiones relacionadas