Pregunta

Esto puede ser para la mayoría de las lenguas en general, pero no estoy seguro. Soy un principiante en Python y siempre he trabajado en las copias de las listas en C # y VB. Pero en Python cuando paso una lista como argumento y enumerar a través de uso de un "for i in range", y luego cambie el valor del argumento de la lista, los valores de entrada cambia realmente la lista original. Pensé Python se suponía que pasar argumentos por valor por defecto para que una vez finalizada la función todavía tengo los valores originales de antes de llamar a la función. ¿Qué me estoy perdiendo? Gracias!

¿Fue útil?

Solución

Python hace pasar argumentos por valor, pero el valor que está recibiendo es una copia de la referencia (por cierto, esto es exactamente del mismo modo que C #, VB.NET y Java se comportan así).

Esto es lo más importante para recordar:

  

Los objetos no se pasan por referencia -. Referencias a objetos se pasan por valor

Dado que usted tiene una copia de la referencia, cualquier operación en lo que los puntos de referencia a será igual que si estuviera sosteniendo la referencia original en sí.

Otros consejos

Python - al igual que Java no para otra cosa que escalares primitivos, y como C # y VB.NET hacer para los parámetros por defecto especie en contraposición a los tipos y en caja fuera parms / ref - Tarjetas "por referencia a un objeto" (búsqueda de esa frase aquí - es cómo Guido, arquitecto y creador de Python, utiliza para explicar este argumento, concepto que pasa).

Cada nombre es una referencia a un objeto; pasando un nombre (o cualquier otra expresión) como un argumento es sólo la creación de todavía otra referencia al mismo objeto (que el cuerpo de la función se puede acceder a través del nombre del parámetro). ((No hay tal cosa como "una referencia a un nombre": hay nombres , que son un tipo de referencia a objetos, y el objeto - período)).

Cuando estás pasando un objeto mutable, es decir, uno que ha mutando métodos (como por ejemplo una lista), la función llamada puede mutar el objeto llamando, directa o indirectamente, sus métodos de mutar. ((Por "indirectamente", es decir "a través de los operadores" - por ejemplo:

somelist[len(somelist):] = [whatever]

es exactamente idéntica a somelist.append(whatever).))

Cuando se quiere pasar una lista en una función, pero hacerlo no quiere que la función sea capaz de mutar esa lista en cualquier forma, debe pasar un copia de la lista en lugar del original -. al igual que en Java, C #, VB.NET

ser muy claro acerca de la distinción entre volver a vincular un nombre y mutando un objeto . Revinculación el nombre ( "barename", es decir - cualificados nombres son diferentes ;-) Sólo afectos que nombre - no cualquier objeto lo que. Por ejemplo:

def f1(alist):
  alist = [23]

def f2(alist):
  alist[:] = [23]

¿Se puede detectar la diferencia entre estas dos funciones? Uno de ellos es la revinculación de la barename alist - sin ningún efecto en absoluto en nada. El otro está mutando (alterar, cambiar, ...) el objeto de lista que recibe como argumento - estableciendo su contenido a ser una lista de un solo elemento con un int como único elemento. completamente, completamente cosas diferentes !!!

Para añadir a la respuesta de Andrew, que necesita para hacer explícita una copia de una lista si desea conservar el original. Para ello, puede utilizar el módulo copy, o simplemente hacer algo como

a = [1,2]
b = list(a)

Desde copiar objetos por lo general implica un impacto en el rendimiento, me resulta útil usar explícitamente el módulo de copia en mis proyectos más grandes. De esa manera, se puede encontrar fácilmente todos los lugares en los que voy a usar un montón más memoria.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top