
On Sat, Apr 16, 2016 at 7:50 PM, Chris Angelico <rosuav@gmail.com> wrote:
Every now and then there's been talk of making it easier to subclass modules, and the most common use case that I can remember hearing about is descriptor protocol requiring code on the type. (For instance, you can't change a module-level constant into a property without moving away from the default ModuleType.)
How bad would it be for the default ModuleType to have a __getattr__ function which defers to the instance? Something like this:
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's not true :-). Code executing inside the module has 'globals() is mod.__dict__', so lookups go directly to mod.__dict__ and skip mod.__getattr__. However, starting in 3.5 cpython allows __class__ assignment on modules, so you can implement custom __getattr__ on a module with: class ModuleWithMyGetattr(types.ModuleType): def __getattr__(self, name): # .. whatever you want ... sys.modules[__name__].__class__ = ModuleWithMyGetattr The advantage of doing it this way is that you can also implement other things like __dir__ (so tab completion on your new attributes will work). This package backports the functionality to earlier versions of CPython: https://pypi.python.org/pypi/metamodule https://github.com/njsmith/metamodule/ Basically just replace the explicit __class__ assignment with import metamodule metamodule.install(__name__, ModuleWithMyGetattr) (See the links above for more details and a worked example.) -n -- Nathaniel J. Smith -- https://vorpus.org