Ho creato del codice Python per utilizzare una classe esterna dalla sua classe interna , basato su una buona idea di un'altra risposta a questa domanda. Penso che sia breve, semplice e facile da capire.
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}
Il codice principale, "pronto per la produzione" (senza commenti, ecc.). Ricordarsi di sostituire tutti i valori tra parentesi angolari (ad esempio <x>
) con il valore desiderato.
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>}
Spiegazione di come funziona questo metodo (i passaggi di base):
Creare una funzione denominata _subclass_container
per fungere da wrapper per accedere alla variabile self
, un riferimento alla classe di livello superiore (dal codice in esecuzione all'interno della funzione).
Creare una variabile denominata _parent_class
che sia un riferimento alla variabile self
di questa funzione, a cui le sottoclassi di _subclass_container
possono accedere (evita conflitti di nome con altre self
variabili nelle sottoclassi).
Restituisce la sottoclasse / sottoclassi come un dizionario / elenco in modo che il codice che chiama la _subclass_container
funzione possa accedere alle sottoclassi all'interno.
Nella __init__
funzione all'interno della classe di livello superiore (o ovunque sia necessario), ricevi le sottoclassi restituite dalla funzione _subclass_container
nella variabile subclasses
.
Assegna le sottoclassi memorizzate nella subclasses
variabile agli attributi della classe di livello superiore.
Alcuni suggerimenti per semplificare gli scenari:
Rendere il codice per assegnare le sottoclassi alla classe di livello superiore più facile da copiare e da utilizzare nelle classi derivate dalla classe di livello superiore che hanno la loro __init__
funzione modificata:
Inserire prima della riga 12 nel codice principale:
def _subclass_init(self):
Quindi inserire in questa funzione le righe 5-6 (del codice principale) e sostituire le righe 4-7 con il seguente codice:
self._subclass_init(self)
Rendere possibile l'assegnazione di sottoclassi alla classe di livello superiore quando ci sono molte / quantità sconosciute di sottoclassi.
Sostituisci la riga 6 con il codice seguente:
for subclass_name in list(subclasses.keys()):
setattr(self, subclass_name, subclasses[subclass_name])
Scenario di esempio in cui questa soluzione sarebbe utile e in cui il nome della classe di livello superiore dovrebbe essere impossibile da ottenere:
Viene class a:
creata una classe denominata "a" ( ). Ha sottoclassi che devono accedervi (il genitore). Una sottoclasse è chiamata "x1". In questa sottoclasse, il codice a.run_func()
viene eseguito.
Quindi viene creata un'altra classe, denominata "b", derivata dalla classe "a" ( class b(a):
). Dopodiché, viene eseguito del codice b.x1()
(chiamando la funzione secondaria "x1" di b, una sottoclasse derivata). Questa funzione viene eseguita a.run_func()
chiamando la funzione "run_func" della classe "a", non la funzione "run_func" del suo genitore, "b" (come dovrebbe), perché la funzione definita nella classe "a" è impostata per fare riferimento alla funzione della classe "a", poiché quella era il suo genitore.
Ciò causerebbe problemi (es. Se la funzione a.run_func
è stata cancellata) e l'unica soluzione senza riscrivere il codice in classe a.x1
sarebbe ridefinire la sottoclasse x1
con codice aggiornato per tutte le classi derivate dalla classe "a" che ovviamente sarebbe difficile e non vale la pena esso.