class Outer(object):
outer_var = 1
class Inner(object):
@property
def inner_var(self):
return Outer.outer_var
Esto no es exactamente lo mismo que funcionan cosas similares en otros lenguajes y utiliza la búsqueda global en lugar de establecer el alcance del acceso a outer_var
. (Si cambia el objeto al que Outer
está vinculado el nombre , este código usará ese objeto la próxima vez que se ejecute).
Si, en cambio, desea que todos los Inner
objetos tengan una referencia a un Outer
porque outer_var
es realmente un atributo de instancia:
class Outer(object):
def __init__(self):
self.outer_var = 1
def get_inner(self):
return self.Inner(self)
# "self.Inner" is because Inner is a class attribute of this class
# "Outer.Inner" would also work, or move Inner to global scope
# and then just use "Inner"
class Inner(object):
def __init__(self, outer):
self.outer = outer
@property
def inner_var(self):
return self.outer.outer_var
Tenga en cuenta que anidar clases es algo poco común en Python y no implica automáticamente ningún tipo de relación especial entre las clases. Es mejor no anidar. (Todavía se puede establecer un atributo de clase en el Outer
que Inner
, si lo desea.)
Outer
se busca de nuevo cada vez que lo haceInner.inner_var
. Entonces, si vuelve a vincular el nombreOuter
a un nuevo objeto,Inner.inner_var
comenzará a devolver ese nuevo objeto.Creo que simplemente puedes hacer:
El problema que encontró se debe a esto:
Lo anterior significa:
un cuerpo de función es un bloque de código y un método es una función, entonces los nombres definidos fuera del cuerpo de la función presente en una definición de clase no se extienden al cuerpo de la función.
Parafraseando esto para su caso:
una definición de clase es un bloque de código, entonces los nombres definidos fuera de la definición de clase interna presente en una definición de clase externa no se extienden a la definición de clase interna.
fuente
[a + i for i in range(10)]
vincula con éxito a Ab con la lista esperada [42..51].list(a + i for i in range(10))
eslist((a + i for i in range(10)))
decirlist(a_generator)
. Dicen que un generador se implementa con un alcance similar al alcance de funciones.list(...)
llamada ni la comprensión funcionan en Python 3. La documentación para Py3 también es ligeramente diferente reflejando esto. Ahora dice " El alcance de los nombres definidos en un bloque de clase se limita al bloque de clase; no se extiende a los bloques de código de métodos; esto incluye comprensiones y expresiones generadoras, ya que se implementan usando un alcance de función " . (Énfasis mío ).Es posible que esté mejor si simplemente no usa clases anidadas. Si debe anidar, intente esto:
O declare ambas clases antes de anidarlas:
(Después de esto, puede
del InnerClass
hacerlo si lo necesita).fuente
Solución más sencilla:
Requiere que seas explícito, pero no requiere mucho esfuerzo.
fuente
En Python, los objetos mutables se pasan como referencia, por lo que puede pasar una referencia de la clase externa a la clase interna.
fuente
__del__
método definido , el recolector de basura no podrá manejar el ciclo de referencia y los objetos entrarángc.garbage
. Sin embargo, el código anterior, tal como está, no es problemático. La forma de lidiar con esto es usando una referencia débil . Puede leer la documentación sobre debilref (2.7) o debilref (3.5)Todas las explicaciones se pueden encontrar en la documentación de Python El tutorial de Python
Por su primer error
<type 'exceptions.NameError'>: name 'outer_var' is not defined
. La explicacion es:citado de The Python Tutorial 9.4
Por tu segundo error
<type 'exceptions.NameError'>: name 'OuterClass' is not defined
citado de The Python Tutorial 9.3.1
Entonces, cuando lo intentas
inner_var = Outerclass.outer_var
,Quterclass
aún no se ha creado, por esoname 'OuterClass' is not defined
Una explicación más detallada pero tediosa de su primer error:
citado de Learning.Python (quinto) .Mark.Lutz
fuente