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_containerpara 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_classque sea una referencia a la variable selfde esta función, a la que _subclass_containerpuedan acceder las selfsubclases 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_containerfunció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_containeren la variable subclasses.
Asignar subclases almacenadas en la subclassesvariable 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_funcse ha eliminado la función) y la única solución sin reescribir el código en la clase a.x1sería redefinir la subclase x1con 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.