2010-11-09 2 views
1

Я строю модульное приложение, и я хотел, чтобы все объекты определенного типа могли вызвать объект управления и автоматически иметь свой собственный экземпляр.Метод переадресации вызова и прохода вызывающего абонента автоматически

Сценарий: Мое приложение состоит из фреймворка и плагинов, которые загружаются во время выполнения. Один из этих плагинов обеспечивает функциональность, которая работает в отдельных контекстах для каждого плагина. Проще говоря: он получает экземпляр плагина вызывающего абонента и работает только с данными, связанными с этим плагином. Во избежание путаницы в нижеследующем описании, обратитесь к вызываемому лицу как к объекту управления и к вызывающему в качестве рабочего объекта. Там будет один объект управления и несколько плагинов: 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, поэтому я, возможно, что-то упустил.

+0

Почему вы не используете обычные декораторы для этого? –

+0

Я не уверен, что понимаю, но мне хотелось бы, чтобы все объекты, которые спускались с определенного типа, имели эту функциональность, и им не нужно ничего менять ничего. «Обычными» декораторами я предполагаю, что вы имеете в виду обозначение @? Разве это не означает, что я делаю это в определении класса? Но этот funcionatliy обеспечивается дополнительным модулем, который загружается во время выполнения. Поэтому в основном я хотел бы иметь атрибут, который действует как общий декоратор, вызывающий метод с тем же именем определенного объекта, что и это имя атрибута этого атрибута. – phant0m

+0

Возможно, более простой ответ на ваш вопрос будет следующим: потому что я не знаю, как добиться этого эффекта иначе - отсюда вопрос. – phant0m

ответ

0

Если все, что вы делаете, это доступ к атрибутам, используйте дескриптор. Похоже, что вы реализуете дескрипторный дизайн и называете его «Wrapper». Дескриптор, вероятно, будет немного проще и более совместим со всеми другими местами на Python, которые используют дескрипторы.

http://docs.python.org/reference/datamodel.html#descriptors

делая это более типичный класс дескриптора может сохранить вашу работу.

+0

Единственная причина, по которой я использую дескриптор, - получить экземпляр, на котором в данный момент работает класс. Опять же, я не знаю, что именно вы хотите, чтобы я сделал. Я вижу, что имя «Wrapper» может быть несколько запутанным на данный момент. Не могли бы вы привести пример кода на то, что вы имели в виду? – phant0m

+0

Или вы имеете в виду, что реализуете все атрибуты класса, к которым я обращаюсь через мой сомнительный путь в качестве дескрипторов, чтобы я мог получить вызывающего из метода __get__ напрямую? – phant0m

+0

подумал, что это не сработает, так как я получу экземпляр вызываемого. Поэтому я вернулся к нулю: я не знаю, что вы имеете в виду. Или я никогда не знал, что я думал, что вы имели в виду. lol – phant0m

Смежные вопросы