Lazy Proxy in Python
Posted by Michał ‘mina86’ Nazarewicz on 8th of July 2012 | (cite)
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.