Я строю модульное приложение, и я хотел, чтобы все объекты определенного типа могли вызвать объект управления и автоматически иметь свой собственный экземпляр.Метод переадресации вызова и прохода вызывающего абонента автоматически
Сценарий: Мое приложение состоит из фреймворка и плагинов, которые загружаются во время выполнения. Один из этих плагинов обеспечивает функциональность, которая работает в отдельных контекстах для каждого плагина. Проще говоря: он получает экземпляр плагина вызывающего абонента и работает только с данными, связанными с этим плагином. Во избежание путаницы в нижеследующем описании, обратитесь к вызываемому лицу как к объекту управления и к вызывающему в качестве рабочего объекта. Там будет один объект управления и несколько плагинов: Object 1 Управление
Я хотел бы объект работник, чтобы иметь возможность получить доступ к функциям управления, без необходимости указать экземпляр рабочего:
Plugin + экземпляр явно указан в списке параметров.
Вместо этого я хотел бы, чтобы методы управления выглядели так, как будто они принадлежали к рабочему объекту, так что передача аргумента вызывающего объекта является прозрачной и неявной.
Возможна одна возможность зарегистрировать все новые методы управления непосредственно с рабочим классом. Однако мне не нравится это «загрязнение пространства имен». Вместо этого я хотел бы, чтобы они были доступны через атрибут, чтобы смысл был понятным.
Имейте в виду, что это поведение добавляется во время выполнения, и я не хочу изменять сам класс Plugin. Кроме того, в то время уже были созданы несколько плагинов, но мне нужно, чтобы это работало для всех текущих и будущих экземпляров.
Идея, которую я придумал, заключается в объединении дескриптора __get__
и __getattr__
методов в один объект.
Метод __get__
будет использоваться для определения экземпляра вызывающего абонента.
Метод будет использоваться для динамического переноса метода, который предполагается вызывать из объекта управления.
код я придумал, как это выглядит:
my_management_object = getItHere()
class Wrapper(object):
def __init__(self):
self._caller = None
def __getattr__(self, name):
method = getattr(my_management_object, name)
def wrapper(*args, **kwargs):
return method(self._caller, *args, **kwargs)
return wrapper
def __get__(self, caller, type):
self._caller = caller
return self
MyPluginClass._manage = Wrapper()
Так что теперь, я могу сделать:
obj = MyPluginClass()
obj._manage.doSomethingForMe()
#vs:
getMyManagementObject().doSomethingForMe(obj)
Я испытал это, и это, кажется, работает. Мне было интересно, есть ли какие-либо подводные камни в этом методе или есть ли более питонические способы сделать это. Я довольно новичок в материалах Descriptor, поэтому я, возможно, что-то упустил.
Почему вы не используете обычные декораторы для этого? –
Я не уверен, что понимаю, но мне хотелось бы, чтобы все объекты, которые спускались с определенного типа, имели эту функциональность, и им не нужно ничего менять ничего. «Обычными» декораторами я предполагаю, что вы имеете в виду обозначение @? Разве это не означает, что я делаю это в определении класса? Но этот funcionatliy обеспечивается дополнительным модулем, который загружается во время выполнения. Поэтому в основном я хотел бы иметь атрибут, который действует как общий декоратор, вызывающий метод с тем же именем определенного объекта, что и это имя атрибута этого атрибута. – phant0m
Возможно, более простой ответ на ваш вопрос будет следующим: потому что я не знаю, как добиться этого эффекта иначе - отсюда вопрос. – phant0m