Есть ли лучший способ выполнить этот или, возможно, другой подход к вышеуказанной проблеме распространения?
Возможно. Модуль Python для установки модуля / пакета, как правило, сложно подделать динамически, как это, но его система объектов / классов открыта и расширяема четко определенным способом. Когда модули и пакеты не совсем обладают необходимыми функциями для инкапсуляции вашего проекта, вы можете использовать классы.
Например, вы можете иметь функциональность расширения в совершенно другом пакете, но позволить ему внедрять классы в базовую среду через определенный интерфейс. например. myframework / _ _ init _ _.py, содержащий базовую оболочку приложения:
class MyFramework(object):
"""A bare MyFramework, I only hold a person's name
"""
_addons= {}
@staticmethod
def addAddon(name, addon):
MyFramework._addons[name]= addon
def __init__(self, person):
self.person= person
for name, addon in MyFramework._addons.items():
setattr(self, name, addon(self))
Тогда вы могли бы иметь функциональность расширения в myexts / helloer.py, который хранит ссылку на свой «владелец» или «внешний» экземпляр класса MyFramework:
class Helloer(object):
def __init__(self, owner):
self.owner= owner
def hello(self):
print 'hello '+self.owner.person
import myframework
myframework.MyFramework.addAddon('helloer', Helloer)
Так что теперь, если вы просто «импортируете myframework», вы получите только базовую функциональность. Но если вы также «импортируете myexts.helloer», вы также получите возможность вызывать MyFramework.helloer.hello (). Естественно, вы также можете определить протоколы для аддонов, чтобы взаимодействовать с базовым поведением фреймворка и друг с другом. Вы также можете делать такие вещи, как внутренние классы, которые можно переопределить подклассом фреймворка, чтобы настраивать его без необходимости исправления классов, которые могут повлиять на другие приложения, если вам нужен такой уровень сложности.
Инкапсуляция поведения, подобного этому, может быть полезной, но обычно это раздражающая работа по адаптации кода уровня модуля, который вам уже подходит для этой модели.