B
Bruno Desthuilliers
bukzor a écrit :
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).
__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.
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 ?
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 attrbject.__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 ?