• mina86.com

  • Categories
  • Code
  • Contact
  • Lazy Proxy in Python

    Posted by Michał ‘mina86’ Nazarewicz on 8th of July 2012

    Paths of destiny lead mysterious ways. Not so long ago, I was a hard-core C hacker and now, I spend a lot of the time coding in Python.

    In somehow related news, I have discovered that my search-foo is not good enough, when I was unable to find a decent implementations of several design patterns in Python.

    What I needed was a generic proxy that would defer initialisation of an object to the moment it is first used. Here is what I came up with:

    class LazyProxy(object):
        __slots__ = '__get'
    
        def __init__(self, cls, *args, **kw):
            object.__setattr__(self, '_LazyProxy__get',
                               lambda: self.__set(cls(*args, **kw)))
    
        def __set(self, obj):
            object.__setattr__(self, '_LazyProxy__get', lambda: obj)
            return obj
    
        def __getattr__(self, name):
            return getattr(self.__get(), name)
    
        def __setattr__(self, name, value):
            return setattr(self.__get(), name, value)
    
        def __delattr__(self, name):
            return delattr(self.__get(), name)

    Here’s how one can use it:

    class Foo(object):
        foo = 'foo'
    
        def __init__(self, bar, baz):
            print 'Creating Foo...'
            self.foo = 'foobar'
            self.bar = bar
            self.baz = baz
    
        def a(self):
            print 'Foo.a: self=(foo=%s, bar=%s, baz=%s)' % (
                self.foo, self.bar, self.baz)
    
        @classmethod
        def b(cls):
            print 'Foo.b: cls=%s, cls.foo=%s' % (
                cls.__name__, cls.foo)
    
        @staticmethod
        def c():
            print 'Foo.c'
    
    foo = LazyProxy(Foo, 'bar', baz='qux')
    print 'LazyProxy created'
    foo.a()
    foo.b()
    foo.c()

    foo can be used in (almost) the same way as an already created Foo object would. The only caveat is it will not be an instance of Foo which may or may not be an issue. Also, it is not thread safe.

    Code © Google Inc.