2013-03-07 2 views
2

У меня есть много классов, реализованных в моем коде. Теперь я понимаю, что для каждого метода вызывается для всех этих классов нужно добавить строку:Прокси-шаблон в Python

with service as object: 

Так что я пытаюсь использовать шаблон прокси автоматически выполнять работу, это мой пример код

class A(object): 
    def __init__(self, name): 
     self.name = name 
    def hello(self): 
     print 'hello %s!' % (self.name) 
    def __enter__(self): 
     print 'Enter the function' 
     return self 
    def __exit__(self, exc_type, exc_value, traceback): 
     print 'Exit the function' 
class Proxy(object): 
    def __init__(self, object_a): 
#  object.__setattr__(self, '_object_a', object_a) 
     self._object_a = object_a 

    def __getattribute__(self, name): 
     service = object.__getattribute__(self, '_object_a') 
     with service as service: 
      result = getattr(service, name) 
     return result  

if __name__=='__main__': 
    a1 = A('A1') 
    b = Proxy(a1) 
    b.hello() 
    a2 = A('A2') 
    b = Proxy(a2) 
    b.hello() 

Все работает найти, у меня есть выход:

Enter the function A1 
Exit the function A1 
hello A1! 
Enter the function A2 
Exit the function A2 
hello A2! 

Но это не совсем мне нужно, потому что мне нужно, это эквивалент:

with a1 as a1: 
    a1.hello() 

И я должен иметь выход:

Enter the function A1 
hello A1! 
Exit the function A1 
Enter the function A2 
hello A2! 
Exit the function A2 

Что мне нужно, чтобы иметь такой результат? Thanks

+0

Этот пример не работает для меня: 'объект 'NoneType' не имеет атрибута«hello''. – poke

+0

Я не знаю, что вы думаете, что означает «с a1 как a1», но это, конечно, не имеет никакого смысла здесь. – danodonovan

+0

Я думаю, что ваш '__enter__' должен возвращать' self' ... – poke

ответ

6

Я хотел бы использовать декоратор:

class Proxy(object): 
    def __init__(self, object_a): 
     self._object_a = object_a 

    def decorateEnterExit(self, obj, f): 
     def inner(*args, **kwargs): 
      with obj as _: 
       return f(*args, **kwargs) 
     return inner 

    def __getattribute__(self, name): 
     obj = object.__getattribute__(self, '_object_a') 
     dee = object.__getattribute__(self, 'decorateEnterExit') 
     return dee(obj, getattr(obj, name)) 

этак с будет оцениваться только тогда, когда функция выполняется. То, как вы это сделали, сначала оценило бы (включая выход из него), а затем функция будет возвращена для вызова. Теперь мы возвращаем функцию, которая сама войдет в функцию и вызовет функцию внутри.

>>> Proxy(A('Ax')).hello() 
Enter the function 
hello Ax! 
Exit the function 

Обратите внимание, что вам нужно возвратить self в методе __enter__ из A:

def __enter__(self): 
    print 'Enter the function' 
    return self 
+0

Спасибо, эта функция работает для меня! – nam

+0

Nice one @poke, спасибо –

0

Вам не нужен оператор возврата в вашем методе , который должен возвращать экземпляр вашего класса (self).

Как насчет вопроса, в вашем Proxy, вероятно, этот результат оценивается после закрытия контекста. Попробуйте это, чтобы увидеть, что вы на самом деле вернуться - это связанный метод:

def __getattribute__(self, name): 
    service = object.__getattribute__(self, '_object_a') 
    with service as service: 
     result = getattr(service, name) 
     print result 
    return result 

это покажет

Enter the function 
<bound method A.hello of <__main__.A object at 0x022A2950>> 
Exit the function 

И только тогда метод вызывается, после __getattribute__ вернулся его.