Proxy pattern in Python

给你一囗甜甜゛ 提交于 2019-12-11 01:36:53

问题


I have a lots of class implemented in my code. Now I realise that for each method invoked for all these classes I need to add a line:

with service as object:

So I'm trying to use the Proxy pattern to automatically do the job, this is my example code

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()

Everything works find, I have the output:

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

But this is not exactly I need, because what I need is the equivalent of:

with a1 as a1:
    a1.hello()

And I must have the output:

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

What i need to have that result? Thanks


回答1:


I would use a decorator:

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))

That way the with will be only evaluated when the function is executed. The way you did it it would first evaluate the with (including exiting it) and then the function would be returned to be called. Now we return a function which will itself enter the with and call the function inside.

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

Note that you need to return self in your __enter__ method of A:

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



回答2:


You are missing a return statement in your __enter__ method, which should return an instance of your class(self).

As about the question, in your Proxy, it is likely, that result is evaluated after the context is closed. Try this to see what you actually return - is a bound method:

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

this will show

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

And only then method is called, after __getattribute__ has returned it.



来源:https://stackoverflow.com/questions/15269774/proxy-pattern-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!