Late initialization using __getattribute__
Bruno Desthuilliers
bdesth.quelquechose at free.quelquepart.fr
Wed Sep 3 15:19:30 EDT 2008
bukzor a écrit :
> I want to make a MixIn class that waits to initialize its super-
> classes until an attribute of the object is accessed. Not generally
> useful, but desirable in my case. I've written this, and it works, but
> would like to take any suggestions you guys have.
You shouldn't mess with __getattribute__ unless you really know what
you're doing and are ok to suffer the constant performance hit you'll
get. Remember that __getattribute__ actually *is* the implementation of
attribute lookup rules, and is called on each and every attribute
lookup. Your below snippet would be much better using __getattr__ (which
is only called as a last resort).
> I've commented out
> the "delattr" call because it throws an AttributeError (although I
> don't know why).
__getattribute__ belongs to the class, not to the instance. delattr()
only removes instance attributes. You'd have to remove __getattribute__
from the LateInitMixIn class object itself, but then it would break the
whole thing.
>
>
> class LateInitMixIn(object):
> def __init__(self):
> print "LateInit initialization"
> self.inited = False
> def __getattribute__(self, attr):
> print "Doing __getattribute__"
> getattr = lambda attr:object.__getattribute__(self, attr)
> if not getattr("inited"):
> super(LateInitMixIn, self).__init__()
> setattr(self, "inited", True)
> #delattr(self, "__getattribute__")
> return getattr(attr)
Here's another possible implementation (which doesn't solve all
problems, cf below) using __getattr__:
class LateInitMixin(object):
def __init__(self):
print "not yet"
self.__initialized = False
def __getattr__(self, name):
if self.__initialized:
raise AttributeError(
"object %s has no attribute '%s'" % (type(self), name)
)
super(LateInitMixin, self).__init__()
self.__initialized = True
return getattr(self, name)
class Base(object):
def __init__(self):
print "yet"
self.base = True
class LateInit(LateInitMixin, Base):
pass
def main():
print "shouldn't init"
S = LateInit()
print "should init"
print S.base
if __name__=="__main__":
main()
Ok, now, the other problem : what if Base.__init__ expects args ?
More information about the Python-list
mailing list