Wrapping classes

bruno modulix onurb at xiludom.gro
Fri Sep 23 04:46:35 EDT 2005


Jeremy Sanders wrote:
> Is it possible to implement some sort of "lazy" creation of objects only
> when the object is used, but behaving in the same way as the object?

Smells like a Proxy pattern...

> For instance:
> 
> class Foo:
>   def __init__(self, val):
>     """This is really slow."""
>     self.num = val
> 
> # this doesn't call Foo.__init__ yet
> a = lazyclass(Foo, 6)
> 
> # Foo is only initalised here
> print a.num
> 
> What I really want to do is make an object which looks like a numarray,
> but only computes its contents the first time it is used.
> 

Here's a Q&D, stupid simple, possibly flawed solution:
class LazyProxy(object):
    def __init__(self, klass, *args, **kwargs):
        self.__klass = klass
        self.__args = args
        self.__kwargs = kwargs
        self.__subject = None

    def __lazy_init(self):
        if self.__subject is None:
            self.__subject = self.__klass(*self.__args,**self.__kwargs)

    def __getattr__(self, name):
        self.__lazy_init()
        return getattr(self.__subject, name)

    def __setattr__(self, name, value):
        # TODO : there's a better way to do this,
        # but I don't remember it ruight now and
	# don't have time to search...
        if name in ['_LazyProxy__klass',
                    '_LazyProxy__args',
                    '_LazyProxy__kwargs',
                    '_LazyProxy__subject']:
            self.__dict__[name] = value
        else:
            self.__lazy_init()
            setattr(self.__subject, name, value)


if __name__ == '__main__':
    class Greeter(object):
        def __init__(self, name):
            self.name = name
        def greet(self, who):
            return "hello %s, my name is %s" % (who, self.name)

    lazy1 = LazyProxy(Greeter, 'toto')
    print lazy1.greet('titi')

    lazy2 = LazyProxy(Greeter, 'lolo')
    lazy2.name = "lili"
    print lazy2.greet(lazy1.name)

Every comment, fix etc welcome.

Now there are probably better ways to do this playing with decorators or
meta-classes.

-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list