This seems to be what I need. My use case is to do lengthy intialization as late as possible. In this case this is to initialize class variables. Does this make sense?
Yup. If they definitely have to be class variables, then yeah, you probably need to use a metaclass. If you're looking for late initialization, Scott David Daniels has a nice descriptor recipe for this:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/363602
Probably this is a better call than using __getattr__. With it, your code might look like[1]:
py> class LazyAttribute(object): ... def __init__(self, calculate_function): ... self._calculate = calculate_function ... def __get__(self, obj, _=None): ... if obj is None: ... return self ... value = self._calculate(obj) ... setattr(obj, self._calculate.func_name, value) ... return value ... py> class Foo(object): ... class __metaclass__(type): ... @LazyAttribute ... def bar(self): ... print 'slow initialization' ... return 'apple' ... py> Foo.bar slow initialization 'apple' py> Foo.bar 'apple'
That way, you define all the attributes that need to be lazily initialized in the __metaclass__ class. If all your classes will have the same lazily initialized attributes, you could also write this like:
py> class BarType(type): ... @LazyAttribute ... def bar(self): ... print 'slow initialization' ... return 'apple' ... py> class Foo(object): ... __metaclass__ = BarType ... py> class Baz(object): ... __metaclass__ = BarType ... py> Foo.bar slow initialization 'apple' py> Foo.bar 'apple' py> Baz.bar slow initialization 'apple' py> Baz.bar 'apple'
But I suspect the former is what you want...
Steve
[1] If you're using Python < 2.4, you'll have to make the decorator call manually, e.g.
def bar(self): ... bar = LazyAttribute(bar) -- http://mail.python.org/mailman/listinfo/python-list