J'ai créé du code Python pour utiliser une classe externe de sa classe interne , basée sur une bonne idée d'une autre réponse à cette question. Je pense que c'est court, simple et facile à comprendre.
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}
Le code principal, "prêt pour la production" (sans commentaires, etc.). N'oubliez pas de remplacer toutes les valeurs entre crochets angulaires (par exemple <x>
) par la valeur souhaitée.
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>}
Explication du fonctionnement de cette méthode (les étapes de base):
Créez une fonction nommée _subclass_container
pour agir comme un wrapper pour accéder à la variable self
, une référence à la classe de niveau supérieur (à partir du code exécuté à l'intérieur de la fonction).
Créez une variable nommée _parent_class
qui est une référence à la variable self
de cette fonction, à laquelle les sous-classes de _subclass_container
peuvent accéder (évite les conflits de nom avec d'autres self
variables dans les sous-classes).
Renvoie la sous-classe / sous-classe sous forme de dictionnaire / liste afin que le code appelant la _subclass_container
fonction puisse accéder aux sous-classes à l'intérieur.
Dans la __init__
fonction à l'intérieur de la classe de niveau supérieur (ou partout où cela est nécessaire), recevez les sous-classes retournées de la fonction _subclass_container
dans la variable subclasses
.
Attribuez des sous-classes stockées dans la subclasses
variable aux attributs de la classe de niveau supérieur.
Quelques conseils pour faciliter les scénarios:
Rendre le code pour affecter les sous-classes à la classe de niveau supérieur plus facile à copier et à utiliser dans les classes dérivées de la classe de niveau supérieur dont la __init__
fonction a été modifiée:
Insérer avant la ligne 12 dans le code principal:
def _subclass_init(self):
Insérez ensuite dans cette fonction les lignes 5-6 (du code principal) et remplacez les lignes 4-7 par le code suivant:
self._subclass_init(self)
Rendre possible l'attribution de sous-classes à la classe de niveau supérieur lorsqu'il existe de nombreuses / quantités inconnues de sous-classes.
Remplacez la ligne 6 par le code suivant:
for subclass_name in list(subclasses.keys()):
setattr(self, subclass_name, subclasses[subclass_name])
Exemple de scénario où cette solution serait utile et où le nom de classe de niveau supérieur devrait être impossible à obtenir:
Une classe, nommée "a" ( class a:
) est créée. Il a des sous-classes qui doivent y accéder (le parent). Une sous-classe est appelée "x1". Dans cette sous-classe, le code a.run_func()
est exécuté.
Ensuite, une autre classe, nommée "b" est créée, dérivée de la classe "a" ( class b(a):
). Après cela, du code s'exécute b.x1()
(appelant la sous-fonction "x1" de b, une sous-classe dérivée). Cette fonction s'exécute a.run_func()
en appelant la fonction "run_func" de la classe "a", et non la fonction "run_func" de son parent, "b" (comme il se doit), car la fonction qui a été définie dans la classe "a" est définie pour faire référence à la fonction de la classe "a", car c'était son parent.
Cela poserait des problèmes (par exemple si la fonction a.run_func
a été supprimée) et la seule solution sans réécrire le code dans la classe a.x1
serait de redéfinir la sous-classe x1
avec du code mis à jour pour toutes les classes dérivées de la classe "a" ce qui serait évidemment difficile et ne vaut pas la peine il.