A veces parece natural tener un parámetro predeterminado que es una lista vacía. Sin embargo, Python da un comportamiento inesperado en estas situaciones .
Si por ejemplo, tengo una función:
def my_func(working_list = []):
working_list.append("a")
print(working_list)
La primera vez que se llama, el valor predeterminado funcionará, pero las llamadas posteriores actualizarán la lista existente (con una "a" en cada llamada) e imprimirán la versión actualizada.
Entonces, ¿cuál es la forma pitónica de obtener el comportamiento que deseo (una lista nueva en cada llamada)?
python
python-3.x
John Mulder
fuente
fuente
Respuestas:
Los documentos dicen que debe usarlo
None
como predeterminado y probarlo explícitamente en el cuerpo de la función.fuente
f()
a una lista, tendrá que llamar af(*l)
cuál es bruto. Peor aún, la implementaciónmate(['larch', 'finch', 'robin'], ['bumble', 'honey', 'queen'])
apestaría con varargs. Mucho mejor si lo esdef mate(birds=[], bees=[]):
.Las respuestas existentes ya han proporcionado las soluciones directas solicitadas. Sin embargo, dado que este es un error muy común para los nuevos programadores de Python, vale la pena agregar la explicación de por qué Python se comporta de esta manera, que está muy bien resumida en " la Guía para autostopistas de Python " como " Argumentos predeterminados mutables ": http: // docs .python-guide.org / es / latest / writing / gotchas /
Cita: " Los argumentos predeterminados de Python se evalúan una vez cuando se define la función, no cada vez que se llama a la función (como en, por ejemplo, Ruby). Esto significa que si usa un argumento predeterminado mutable y lo muta, lo hará y tendrá mutado ese objeto para todas las llamadas futuras a la función también "
Código de muestra para implementarlo:
fuente
No es que importe en este caso, pero puede usar la identidad del objeto para probar Ninguno:
También puede aprovechar cómo se define el operador booleano o en python:
Aunque esto se comportará inesperadamente si la persona que llama le da una lista vacía (que cuenta como falsa) como working_list y espera que su función modifique la lista que le dio.
fuente
Si la intención de la función es modificar el parámetro pasado como
working_list
, vea la respuesta de HenryR (= Ninguno, marque Ninguno adentro).Pero si no tenía la intención de mutar el argumento, simplemente utilícelo como punto de partida para una lista, simplemente puede copiarlo:
(o en este simple caso,
print starting_list + ["a"]
pero supongo que fue solo un ejemplo de juguete)En general, mutar tus argumentos es de mal estilo en Python. Las únicas funciones que se espera que muten un objeto son los métodos del objeto. Es incluso más raro mutar un argumento opcional: ¿es un efecto secundario que ocurre solo en algunas llamadas realmente la mejor interfaz?
Si lo hace desde el hábito de C de "argumentos de salida", eso es completamente innecesario: siempre puede devolver múltiples valores como una tupla.
Si hace esto para construir de manera eficiente una larga lista de resultados sin crear listas intermedias, considere escribirlo como un generador y usarlo
result_list.extend(myFunc())
cuando lo llame. De esta manera, sus convenciones de llamadas se mantienen muy limpias.Un patrón en el que se hace con frecuencia la mutación de un argumento opcional es un argumento "memo" oculto en funciones recursivas:
fuente
Puede que esté fuera de tema, pero recuerde que si solo desea pasar un número variable de argumentos, la forma pitónica es pasar una tupla
*args
o un diccionario**kargs
. Estos son opcionales y son mejores que la sintaxismyFunc([1, 2, 3])
.Si desea pasar una tupla:
Si quieres pasar un diccionario:
fuente
Ya se han proporcionado respuestas buenas y correctas. Solo quería dar otra sintaxis para escribir lo que quieres hacer, lo que encuentro más hermoso cuando, por ejemplo, quieres crear una clase con listas vacías predeterminadas:
Este fragmento hace uso de la sintaxis del operador if else. Me gusta especialmente porque es una frase sencilla sin dos puntos, etc., y casi se lee como una oración normal en inglés. :)
En tu caso podrías escribir
fuente
Tomé la clase de extensión UCSC
Python for programmer
Lo cual es cierto de: def Fn (data = []):
Responder:
fuente