Stworzyłem kod w Pythonie, aby używać zewnętrznej klasy z jej klasy wewnętrznej , w oparciu o dobry pomysł z innej odpowiedzi na to pytanie. Myślę, że jest krótki, prosty i łatwy do zrozumienia.
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}
Główny kod „do produkcji” (bez komentarzy itp.). Pamiętaj, aby zastąpić wszystkie wartości w nawiasach ostrych (np. <x>
) Żądaną wartością.
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>}
Wyjaśnienie, jak działa ta metoda (podstawowe kroki):
Utwórz funkcję o nazwie, _subclass_container
która będzie działać jako opakowanie, aby uzyskać dostęp do zmiennej self
, odwołanie do klasy wyższego poziomu (z kodu działającego wewnątrz funkcji).
Utwórz zmienną o nazwie, _parent_class
która jest odniesieniem do zmiennej self
tej funkcji, do której podklasy _subclass_container
mają dostęp (pozwala to uniknąć konfliktów nazw z innymi self
zmiennymi w podklasach).
Zwróć podklasy / podklasy jako słownik / listę, aby kod wywołujący _subclass_container
funkcję mógł uzyskać dostęp do podklas wewnątrz.
W __init__
funkcji wewnątrz klasy wyższego poziomu (lub gdziekolwiek jest to potrzebne), odbierz zwrócone podklasy z funkcji _subclass_container
do zmiennej subclasses
.
Przypisz podklasy przechowywane w subclasses
zmiennej do atrybutów klasy wyższego poziomu.
Kilka wskazówek ułatwiających scenariusze:
Ułatwienie kopiowania kodu przypisującego podklasy do klasy wyższego poziomu i używanie go w klasach pochodnych klasy wyższego poziomu, które mają __init__
funkcja została zmieniona:
Wstaw przed linią 12 w głównym kodzie:
def _subclass_init(self):
Następnie wstaw do tej funkcji wiersze 5-6 (głównego kodu) i zamień wiersze 4-7 na następujący kod:
self._subclass_init(self)
Umożliwienie przypisywania podklas do klasy wyższego poziomu, gdy istnieje wiele / nieznanych ilości podklas.
Zastąp wiersz 6 następującym kodem:
for subclass_name in list(subclasses.keys()):
setattr(self, subclass_name, subclasses[subclass_name])
Przykładowy scenariusz, w którym to rozwiązanie byłoby przydatne i gdzie nie można uzyskać nazwy klasy wyższego poziomu:
Tworzona jest klasa o nazwie „a” ( class a:
). Ma podklasy, które muszą mieć do niego dostęp (rodzic). Jedna podklasa nosi nazwę „x1”. W tej podklasie kod a.run_func()
jest uruchamiany.
Następnie tworzona jest inna klasa o nazwie „b”, pochodząca z klasy „a” ( class b(a):
). Następnie zostaje uruchomiony jakiś kod b.x1()
(wywołanie funkcji podrzędnej „x1” z b, pochodnej podklasy). Ta funkcja działa a.run_func()
, wywołując funkcję „run_func” klasy „a”, a nie funkcję „run_func” jej rodzica, „b” (tak jak powinna), ponieważ funkcja, która została zdefiniowana w klasie „a” ma odwoływać się do funkcji klasy „a”, ponieważ była ona jej rodzicem.
Spowodowałoby to problemy (np. Gdyby funkcja a.run_func
została usunięta), a jedynym rozwiązaniem bez przepisywania kodu w klasie a.x1
byłoby ponowne zdefiniowanie podklasy x1
ze zaktualizowanym kodem dla wszystkich klas pochodzących z klasy „a”, co oczywiście byłoby trudne i niewarte to.