Wrapping classes

Pedro Werneck pedro.werneck at terra.com.br
Fri Sep 23 17:17:34 EDT 2005


I agree this is a case for using metaclasses. What about an
implementation like this ? Seems like checking if init was already
called will slow down all attribute access significantly, but, I don't
like this approach of changing the __init__ method. 


class LazyInit(type):
    def __new__(self, name, bases, dict):

        def __getattribute__(self, attr):
            attrs = object.__getattribute__(self, "__dict__")
            init = attrs["_init"]
            if not init:
                args = attrs["_args"]
                kwds = attrs["_kwds"]
                __init__ = object.__getattribute__(self, "__init__")
                __init__(*args, **kwds)
                attrs["_init"] = True
                
            return object.__getattribute__(self, attr)

        dict['__getattribute__'] = __getattribute__
        return type.__new__(self, name, bases, dict)
    
    def __call__(cls, *args, **kwds):
        o = object.__new__(cls, *args, **kwds)
        o._args = args
        o._kwds = kwds
        o._init = False

        return o


And some simple testing:

>>> class Foo:
...     __metaclass__ = LazyInit
...     def __init__(self, x, y):
...             print "init was called", x, y     
...             self.x = x
...             self.y = y
... 
>>> o = Foo(1, None)
>>> o
<__main__.Foo object at 0x402cc96c>
>>> o.x
init was called 1 None
1
>>> o.y
>>> 


Regards,

Pedro

On Fri, 23 Sep 2005 10:28:42 +0200
Paolino <paolo_veronelli at tiscali.it> wrote:

> 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?
> > 
> A generic approach would override __getattribute__ to let it perform
> the 
>   __init__ method on not initialized objects.This is a case for using 
> metaclasses as even __init__ method must be overridden ad hoc to 
> register the arguments for the lazy initialization.
> Probably you want to fine-tune the triggering (specifing which
> attribute  should make it happen ),as every look up would trigger.....
> 
> class NotInitializedObjects(type):
>    def __init__(cls,*_):
>      realInit=cls.__init__
>      def __newInit__(self,*pos,**key):
>        def _init():
>          realInit(self,*pos,**key)
>        self._init=_init
>      cls.__init__=__newInit__
>      def __getattribute__(self,attr):
>        def getter(attr):
>          return object.__getattribute__(self,attr)
>        if '_init' in getter('__dict__'):
>          getter('_init')()
>          del self._init
>        return getter(attr)
>      cls.__getattribute__=__getattribute__
> 
> 
> if __name__=='__main__':
>    class Class:
>      __metaclass__=NotInitializedObjects
>      def __init__(self,*pos,**key):
>        self.initialized=True
>        print 'initializing with',pos,key
>    a=Class('arg',key='key') # a fake initialization
> 
>    try:
>     object.__getattribute__(a,'initialized')
>    except AttributeError: # should raise
>     print 'not initialized'
>    else:
>     raise
>    try:
>     a.initialized  #every look up would do ,even a print
>    except AttributeError:
>     raise
>    else:
>     print 'initialized'
> 
> 
> Have fun Paolino
> 
> 	
> 
> 	
> 		
> ___________________________________ 
> Yahoo! Mail: gratis 1GB per i messaggi e allegati da 10MB 
> http://mail.yahoo.it
> -- 
> http://mail.python.org/mailman/listinfo/python-list


-- 
Pedro Werneck



More information about the Python-list mailing list