Issue
How can implement the equivalent of a __getattr__
on a class, on a module?
Example
When calling a function that does not exist in a module's statically defined attributes, I wish to create an instance of a class in that module, and invoke the method on it with the same name as failed in the attribute lookup on the module.
class A(object):
def salutation(self, accusative):
print "hello", accusative
# note this function is intentionally on the module, and not the class above
def __getattr__(mod, name):
return getattr(A(), name)
if __name__ == "__main__":
# i hope here to have my __getattr__ function above invoked, since
# salutation does not exist in the current namespace
salutation("world")
Which gives:
matt@stanley:~/Desktop$ python getattrmod.py
Traceback (most recent call last):
File "getattrmod.py", line 9, in <module>
salutation("world")
NameError: name 'salutation' is not defined
Solution
A while ago, Guido declared that all special method lookups on
new-style classes bypass __getattr__
and __getattribute__
. Dunder methods had previously worked on modules - you could, for example, use a module as a context manager simply by defining __enter__
and __exit__
, before those tricks broke.
Recently some historical features have made a comeback, the module __getattr__
among them, and so the existing hack (a module replacing itself with a class in sys.modules
at import time) should be no longer necessary.
In Python 3.7+, you just use the one obvious way. To customize attribute access on a module, define a __getattr__
function at the module level which should accept one argument (name of attribute), and return the computed value or raise an AttributeError
:
# my_module.py
def __getattr__(name: str) -> Any:
...
This will also allow hooks into "from" imports, i.e. you can return dynamically generated objects for statements such as from my_module import whatever
.
On a related note, along with the module getattr you may also define a __dir__
function at module level to respond to dir(my_module)
. See PEP 562 for details.
Answered By - wim
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.