On Sep 3, 12:19 pm, Bruno Desthuilliers <[EMAIL PROTECTED]> wrote: > 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 ?
Thanks for the reply. Just to see it not work, I tried to remove __getattribute__ from LateInitMixIn, but couldn't get it to work. My Base class is a C class (_mysql.connection from MySQLdb) that sometimes segfaults if you try to use it before it's fully initialized, so unfortunately I think I need to use __getattribute__ to do this. I'm doing all this just to make the connection not actually connect until used. -- http://mail.python.org/mailman/listinfo/python-list