Я создал код 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", поскольку он был его родителем.
Это вызовет проблемы (например, если функция a.run_func
была удалена), и единственным решением без перезаписи кода в классе a.x1
будет переопределение подкласса x1
с обновленным кодом для всех классов, производных от класса "а", что, очевидно, будет сложно. и не стоит.
person
Edward
schedule
31.01.2016
self.<original_parent_name>
и получить исходный класс, а не новый класс, от которого они являются подклассом. Я надеюсь, что люди, читающие это, смогут визуализировать этот сложный сценарий и увидеть смысл таких вопросов. - person Edward   schedule 01.02.2016