[Python-Dev] Autoloading? (Making Queue.Queue easier to use)

Nick Coghlan ncoghlan at gmail.com
Thu Oct 13 13:41:31 CEST 2005


Greg Ewing wrote:
> BTW, I agree that special *syntax* isn't necessarily
> needed. But it does seem to me that some sort of
> hook is needed somewhere to make this doable
> smoothly, that doesn't exist today.

Having module attribute access obey the descriptor protocol (__get__, __set__, 
__delete__) sounds like a pretty good option to me.

It would even be pretty backwards compatible, as I'd be hardpressed to think 
why anyone would have a descriptor *instance* as a top-level object in a 
module (descriptor definition, yes, but not an instance).

Consider lazy instance attributes:

Py> def lazyattr(func):
...     class wrapper(object):
...         def __get__(self, instance, cls):
...             val = func()
...             setattr(instance, func.__name__, val)
...             return val
...     return wrapper()
...
Py> class test(object):
...     @lazyattr
...     def foo():
...         print "Evaluating foo!"
...         return "Instance attribute"
...
Py> t = test()
Py> t.foo
Evaluating foo!
'Instance attribute'
Py> t.foo
'Instance attribute'

And lazy class attributes:

Py> def lazyclassattr(func):
...     class wrapper(object):
...         def __get__(self, instance, cls):
...             val = func()
...             setattr(cls, func.__name__, val)
...             return val
...     return wrapper()
...
Py> class test(object):
...     @lazyclassattr
...     def bar():
...         print "Evaluating bar!"
...         return "Class attribute"
...
Py> test.bar
Evaluating bar!
'Class attribute'
Py> test.bar
'Class attribute'


Unfortunately, that trick doesn't work at the module level:

Py> def lazymoduleattr(func):
...     class wrapper(object):
...         def __get__(self, instance, cls):
...             val = func()
...             globals()[func.__name__] = val
...             return val
...     return wrapper()
...
Py> @lazymoduleattr
... def baz():
...     print "Evaluating baz!"
...     return "Module attribute"
...
Py> baz # Descriptor not invoked
<__main__.wrapper object at 0x00B9E3B0>
Py> import sys
Py> main = sys.modules["__main__"]
Py> main.baz # Descriptor STILL not invoked :(
<__main__.wrapper object at 0x00B9E3B0>

But putting the exact same descriptor in a class lets it work its magic:

Py> class lazy(object):
...   baz = baz
...
Py> lazy.baz
Evaluating baz!
'Module attribute'
Py> baz
'Module attribute'

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://boredomandlaziness.blogspot.com


More information about the Python-Dev mailing list