Tutorial de Python -

Advertencia importante: el valor predeterminado se evalúa solo una vez ... Si no desea que el valor predeterminado sea compartido entre llamadas posteriores, usted puede escribir la función así en lugar:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

Todavía esperaba:

print f(1)    # [1]
print f(2)    # [1,2]
print f(3)    # [1,2,3]

Yo razoné:

El valor predeterminado (L=None) se ejecutó para f(1), lo que ayudó a L a señalar una nueva lista vacía en el cuerpo fn. Sin embargo, en llamadas sucesivas, L=None no se ejecutó; así que L todavía apunta a la lista que ya tiene 1, y las llamadas posteriores simplemente le agregan más elementos para compartir L.

¿Dónde estoy pensando incorrectamente?


ACTUALIZACIÓN

def f(a, L=[]):
    L.append(a)
    return L

¿L aquí apunta a una lista vacía creada en el montón o pila?

-1
Vaibhav Bajpai 4 jul. 2011 a las 08:39

3 respuestas

La mejor respuesta

L es el nombre de un argumento, pero es también una variable local. Volver a vincularlo vuelve a vincular la variable local, pero no cambia el argumento predeterminado.

EDICIÓN DE ACTUALIZACIÓN:

Python no tiene "montón" y "pila" de la misma manera que C; todo lo que tiene son objetos y referencias a esos objetos. Su llamada a la función devuelve una referencia a la misma lista que se creó como valor predeterminado para el argumento L de la función f, y cualquier operación que la mute mutará el valor del argumento predeterminado.

2
Ignacio Vazquez-Abrams 4 jul. 2011 a las 05:14

Si ejecuta las funciones a continuación, le ayudará a ver cómo funciona.

def f(a, L=[]):
    print("id default: ", id(L))
    L.append(a)
    print("id used: ", id(L)
    return L

Observe la dirección del objeto 1, estamos usando solo el objeto de lista predeterminado y lo estamos cambiando.

def f(a, L=[]):
    print("id default: ", id(L))
    if L == []:
        L = []
    L.append(a)
    print("id used: ", id(L))      
    return L 

Observe 2 direcciones de objeto diferentes, cuando asigna L = [] nuevamente en la función, está utilizando un objeto de lista diferente y no el objeto de lista predeterminado, y es por eso que el objeto de lista predeterminado no cambia.

def f(a, L=None):
    print("id default", id(L))
    if L is None:
        L = []
    L.append(a) 
    print("id used: ", id(L))      
    return L 

Esta función es básicamente la misma que la anterior, la misma idea, pero utiliza un objeto None en lugar de un objeto de lista vacío.

0
KN Nguyen 31 mar. 2015 a las 19:27

The default value is evaluated only once

Significa que si lo hace def foo(a, b=len([1,2,3])) b se establecerá en 3 y no realizará ninguna llamada de función a len si llama a foo.

El operador = asigna un objeto a un nombre. No cambia el objeto anterior.

0
4 jul. 2011 a las 05:02