He creado un código Python para usar una clase externa de su clase interna , basado en una buena idea de otra respuesta para esta pregunta. Creo que es breve, simple y fácil de entender.
class higher_level__unknown_irrelevant_name__class:
def __init__(self, ...args...):
...other code...
# Important lines to access sub-classes.
subclasses = self._subclass_container()
self.some_subclass = subclasses["some_subclass"]
del subclasses # Free up variable for other use.
def sub_function(self, ...args...):
...other code...
def _subclass_container(self):
_parent_class = self # Create access to parent class.
class some_subclass:
def __init__(self):
self._parent_class = _parent_class # Easy access from self.
# Optional line, clears variable space, but SHOULD NOT BE USED
# IF THERE ARE MULTIPLE SUBCLASSES as would stop their parent access.
# del _parent_class
class subclass_2:
def __init__(self):
self._parent_class = _parent_class
# Return reference(s) to the subclass(es).
return {"some_subclass": some_subclass, "subclass_2": subclass_2}
El código principal, "listo para producción" (sin comentarios, etc.). Recuerde reemplazar todos los valores entre corchetes angulares (por ejemplo <x>
) con el valor deseado.
class <higher_level_class>:
def __init__(self):
subclasses = self._subclass_container()
self.<sub_class> = subclasses[<sub_class, type string>]
del subclasses
def _subclass_container(self):
_parent_class = self
class <sub_class>:
def __init__(self):
self._parent_class = _parent_class
return {<sub_class, type string>: <sub_class>}
Explicación de cómo funciona este método (los pasos básicos):
Cree una función nombrada _subclass_container
para actuar como un contenedor para acceder a la variable self
, una referencia a la clase de nivel superior (del código que se ejecuta dentro de la función).
Cree una variable nombrada _parent_class
que sea una referencia a la variable self
de esta función, a la que _subclass_container
puedan acceder las self
subclases de (evita conflictos de nombre con otras variables en subclases).
Devuelve la subclase / subclases como un diccionario / lista para que el código que llame a la _subclass_container
función pueda acceder a las subclases internas.
En la __init__
función dentro de la clase de nivel superior (o donde sea necesario), reciba las subclases devueltas de la función _subclass_container
en la variable subclasses
.
Asignar subclases almacenadas en la subclasses
variable a atributos de la clase de nivel superior.
Algunos consejos para facilitar los escenarios:
Haciendo que el código para asignar las subclases a la clase de nivel superior sea más fácil de copiar y usar en clases derivadas de la clase de nivel superior que tienen su __init__
función cambiada:
Inserte antes de la línea 12 en el código principal:
def _subclass_init(self):
Luego inserte en esta función las líneas 5-6 (del código principal) y reemplace las líneas 4-7 con el siguiente código:
self._subclass_init(self)
Hacer posible la asignación de subclases a la clase de nivel superior cuando hay muchas / desconocidas cantidades de subclases.
Reemplace la línea 6 con el siguiente código:
for subclass_name in list(subclasses.keys()):
setattr(self, subclass_name, subclasses[subclass_name])
Escenario de ejemplo en el que esta solución sería útil y donde el nombre de clase de nivel superior debería ser imposible de obtener:
Se class a:
crea una clase, denominada "a" ( ). Tiene subclases que necesitan acceder a él (el padre). Una subclase se llama "x1". En esta subclase, a.run_func()
se ejecuta el código .
Luego se crea otra clase, llamada "b", derivada de la clase "a" ( class b(a):
). Después de eso, se ejecuta algún código b.x1()
(llamando a la subfunción "x1" de b, una subclase derivada). Esta función se ejecuta a.run_func()
, llamando a la función "run_func" de la clase "a", no a la función "run_func" de su padre, "b" (como debería), porque la función que se definió en la clase "a" está configurada para referirse a la función de la clase "a", ya que era su padre.
Esto causaría problemas (por ejemplo, si a.run_func
se ha eliminado la función) y la única solución sin reescribir el código en la clase a.x1
sería redefinir la subclase x1
con código actualizado para todas las clases derivadas de la clase "a", lo que obviamente sería difícil y no valdría la pena. eso.