2010-02-22 14 views
8

estoy notando el siguiente:El valor por defecto en una función en Python

class c: 
    def __init__(self, data=[]): 
    self._data=data 
a=c() 
b=c() 
a._data.append(1) 
print b._data 
[1] 

Es este el comportamiento correcto?

+2

Lea la documentación de marcado para ver cómo formatear correctamente el código. Está en el lado derecho de la página. Por favor actualice su pregunta para sangrar el código de 4 espacios. –

+0

relacionadas: http://stackoverflow.com/questions/1011431/python-things-one-must-avoid, http://stackoverflow.com/questions/1534407/python-object-intialization-bug-or-am-i -misunderstanding-cómo-objetos-trabajo, http://stackoverflow.com/questions/1651154/why-are-default-arguments-evaluated-at-definition-time-in-python –

Respuesta

11

Sí, es comportamiento correcto.

Sin embargo, a partir de su pregunta, parece que no es lo que esperaba.

Si usted quiere que coincide con sus expectativas, tenga en cuenta lo siguiente:

Regla 1. No utilice objetos mutables como valores por defecto.

def anyFunction(arg=[]): 

No se creará un objeto de lista nuevo. El objeto de lista predeterminado para arg se compartirá por todas partes.

Del mismo modo

def anyFunction(arg={}): 

no creará un objeto dict fresco. Este dict predeterminado será compartido.

class MyClass(object): 
    def __init__(self, arg= None): 
     self.myList= [] if arg is None else arg 

Esa es una forma común de proporcionar un valor de argumento predeterminado que es un objeto de lista nuevo y vacío.

+3

'nunca work.' es un poco duro. 'No te dará un nuevo objeto mutable vacío en cada llamada', parece un poco más equilibrado. Si sabe que esto sucede, es posible que desee utilizar este comportamiento. – MattH

+0

@MattH: Reutilizar el mismo objeto mutable a través de un valor predeterminado es tan extraño que resulta difícil encontrar un caso de uso sensato. Es un valor * predeterminado *, por lo que puede (o no) utilizarse como tal dependiendo del uso de la interfaz por parte del cliente. Sería tan difícil diagnosticar problemas con esto que estoy de acuerdo con mi formulación original. Especialmente para n00bz. –

+0

Debe agregar un ejemplo de cómo solucionar esto. De lo contrario, la respuesta es buena y correcta. – ironfroggy

1

Siempre hacen funciones como esta a continuación:

def __init__ (self, data = None): 
    if data is None: 
     data = [] 

    self._data = data 

Como alternativa también se puede utilizar data = data or [], pero que impide que el usuario pase a vacías parámetros ('', 0, False etc.).

+0

Por supuesto, también puede hacer 'if not data: data = []'. – voyager

+0

su ejemplo 'data = data or []' funciona bien para las listas vacías que se pasan. Usted diría que 'data' será' [] o [] 'para que vea el primero y vea que se evalúa como" falso ", luego tomará el otro valor. – tgray

+1

Lo sé, mi punto fue que cuando pasa 'False' por ejemplo,' [] 'se usará como el valor, aunque pasó' False'. – poke

Cuestiones relacionadas