2009-07-01 6 views

Respuesta

3

El cuerpo de la clase se ejecuta antes de que se defina la clase propia, por lo que los valores del argumento predeterminado no pueden hacer referencia a la clase. Simplemente haciendo custom el valor predeterminado (sin calificación de clase) debería funcionar.

11

Es Foo que no está visible, porque está en el medio de construirlo. Pero ya que estás en el mismo alcance que custom, sólo se puede decir custom en lugar de Foo.custom:

class Foo(object): 
    custom = 1 
    def __init__(self, mycustom=custom): 
     self._custom = mycustom 

Pero tenga en cuenta que el cambio de Foo.custom más adelante no afectará el valor de custom que posteriormente crearon Foo-s ver :

class Foo(object): 
    custom = 1 
    def __init__(self, mycustom=custom): 
     self._custom = mycustom 

one = Foo() 
Foo.custom = 2 
two = Foo() 
print (two._custom) # Prints 1 

mediante el uso de un valor por defecto en lugar centinela, se puede obtener lo que desea:

class Foo(object): 
    custom = 1 
    def __init__(self, mycustom=None): 
     if mycustom is None: 
      self._custom = Foo.custom 
     else: 
      self._custom = mycustom 

one = Foo() 
Foo.custom = 2 
two = Foo() 
print (two._custom) # Prints 2 
+0

Bueno, excepto que las comparaciones con None siempre deben hacerse a través de 'is'. –

+0

"Aunque eso significa que cambiar Foo.customer más tarde no afectará el valor de la costumbre que los Foos creados posteriormente ven": Vale la pena señalar que siempre es el caso para las funciones que los valores predeterminados se crean y se vinculan solo una vez, cuando la función se crea, por lo que incluso * si * era posible hacer referencia a Foo.custom para un valor predeterminado, todavía sería el caso de que el valor predeterminado no cambiara si se cambiara Foo.custom. – Miles

+0

¿Por qué está permitido hacer referencia a Foo.custom en el cuerpo de __init__ pero no en la lista de inicializadores? En ambos casos, "estamos en el medio de construirlo". –

2

me sale el siguiente error:

Traceback (most recent call last): 
    Line 1, in <module> 
    class Foo(object): 
    Line 3, in Foo 
    def __init__(self, custom=Foo.custom): 
NameError: name 'Foo' is not defined 

Esto se debe a que el nombre Foo está en proceso de ser definida como se define la función __init__ y no está totalmente disponible en ese momento.

La solución es evitar el uso del nombre Foo en la definición de función (que también cambió el nombre del parametro custom a acustom para distinguirlo de Foo.custom):

class Foo(object): 
    custom = 1 
    def __init__(self, acustom=custom): 
     self._custom = acustom 
x = Foo() 
print x._custom 
+0

Pero sabes que puedes consultar Foo.custom en _body_ of __init__, no solo en la lista de inicializadores. Esto me parece inconsistente. –

+0

"También renombré el parámetro personalizado para acostumbrarme a distinguirlo de Foo.custom": esta es probablemente una buena idea, pero no es estrictamente necesario, y en algunas situaciones en Python es incluso una expresión idiomática que sean iguales (principalmente con funciones anidadas dentro de un bucle, por ejemplo, lambda x = x: ...) – Miles

6

, lo que hacemos es la siguiente

class Foo(object): 
    custom = 1 
    def __init__(self, arg=None) 
     self._custom = self.custom if arg is None else arg 

Esto omite la cuestión confusa de si el nombre Foo se ha definido o no.

+0

¿Por qué debería ser confuso? Antes de crear una instancia, la clase debe inicializarse. __init__ se ejecuta cuando se crea una instancia, por lo que las variables de clase deben ser visibles. –

+0

@rdm: Vea el comentario de Miles sobre mi respuesta. Los parámetros predeterminados se determinan durante la creación de la función (es decir, durante la creación de la clase en este caso), no cuando se la llama. – RichieHindle

Cuestiones relacionadas