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 ?

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to