[Python-ideas] __getattr__ bouncer for modules

Chris Angelico rosuav at gmail.com
Sat Apr 16 23:42:46 EDT 2016


On Sun, Apr 17, 2016 at 1:26 PM, Random832 <random832 at fastmail.com> wrote:
> On Sat, Apr 16, 2016, at 22:50, Chris Angelico wrote:
>> def __getattr__(self, name):
>>     if '__getattr__' in self.__dict__:
>>         return self.__dict__['__getattr__'](name)
>>     raise AttributeError
>>
>> The biggest downside I'm seeing is that module attributes double as
>> global names, which might mean this would get checked for every global
>> name that ends up being resolved from the builtins (which is going to
>> be a LOT). But I'm not sure if that's even true.
>
> It is not. (Also, incidentally, defining a global called __class__ does
> not set the module's class.)
>
> I don't think this would be enough alone to let you use property
> decorators on a module - you'd have to explicitly define a __getattr__
> (and __setattr__). And of course make sure that the names you're using
> as properties don't exist as real members of the module, since you're
> using __getattr__ instead of __getattribute__.

Right, it wouldn't automatically allow the use of properties *as
such*, but you would be able to achieve most of the same goal.

# Version 1
BITS_PER_BYTE = 8
BITS_PER_WORD = 32

# Version 2 - doesn't work
BITS_PER_BYTE = 8
@property
def BITS_PER_WORD():
    return 32 or 64

# Version 3 - could work
BITS_PER_BYTE = 8
def __getattr__(name):
    if name == 'BITS_PER_WORD':
        return 32 or 64
    raise AttributeError


It's not as clean as actually supporting @property, but it could be
done without the "bootstrap problem" of trying to have a module
contain the class that it's to be an instance of. All you have to do
is define __getattr__ as a regular top-level function, and it'll get
called. You can then dispatch to property functions if you wish (eg
"""return globals()['_property_'+name]()"""), or just put all the code
straight into __getattr__.

ChrisA


More information about the Python-ideas mailing list