Я создал код 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», что, очевидно, было бы сложно и не стоит Это.