Я створив певний код Python для використання зовнішнього класу з його внутрішнього класу , спираючись на гарну ідею з іншої відповіді на це питання. Я думаю, що це коротко, просто та зрозуміло.
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}
Основний код, "виробництво готове" (без коментарів тощо). Не забудьте замінити всі значення в кутових дужках (наприклад <x>
) потрібними значеннями.
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>}
Пояснення того, як працює цей метод (основні кроки):
Створіть функцію з іменем, яка _subclass_container
буде діяти як обгортка для доступу до змінної self
, посилання на клас вищого рівня (з коду, що працює всередині функції).
Створіть змінну з іменем, _parent_class
яка є посиланням на змінну self
цієї функції, до якої _subclass_container
можуть мати доступ self
підкласи (уникає конфліктів імен з іншими змінними в підкласах).
Поверніть підклас / підкласи як словник / список, щоб код, що викликає _subclass_container
функцію, міг отримати доступ до підкласів всередині.
У __init__
функції всередині класу вищого рівня (або там, де це ще потрібно) отримайте повернені підкласи від функції _subclass_container
до змінної subclasses
.
Призначте підкласи, що зберігаються у subclasses
змінній, атрибутам класу вищого рівня.
Кілька порад для спрощення сценаріїв:
Зробити код для присвоєння підкласів класу вищого рівня простішим для копіювання та використання в класах, похідних від класу вищого рівня, які змінили свої __init__
функції:
Вставте перед рядком 12 в основний код:
def _subclass_init(self):
Потім вставте в цю функцію рядки 5-6 (основного коду) і замініть рядки 4-7 таким кодом:
self._subclass_init(self)
Уможливлення присвоєння підкласу класу вищого рівня, коли існує багато / невідома кількість підкласів.
Замініть рядок 6 таким кодом:
for subclass_name in list(subclasses.keys()):
setattr(self, subclass_name, subclasses[subclass_name])
Приклад сценарію, де це рішення було б корисним, а де найменування класу вищого рівня неможливо отримати:
Створюється клас із назвою "a" ( class a:
). У ньому є підкласи, до яких потрібно отримати доступ (батьківський). Один підклас називається "x1". У цьому підкласі a.run_func()
виконується код .
Потім створюється інший клас з назвою "b", похідний від класу "a" ( class b(a):
). Після цього запускається деякий код b.x1()
(виклик підфункції "x1" з b, похідного підкласу). Ця функція виконується a.run_func()
, викликаючи функцію "run_func" класу "a", а не функцію "run_func" свого батька, "b" (як слід), оскільки функція, яку було визначено в класі "a", встановлена для посилання до функції класу "а", оскільки він був його батьківським.
Це може спричинити проблеми (наприклад, якщо функцію a.run_func
було видалено), і єдиним рішенням без переписування коду в класі a.x1
було б перевизначення підкласу x1
з оновленим кодом для всіх класів, похідних з класу "a", що, очевидно, було б складно і не варто це.