Search code examples
pythonvariable-assignmentlookupquotingredefine

Python __setattr__ and __getattr__ for global scope?


Suppose I need to create my own small DSL that would use Python to describe a certain data structure. E.g. I'd like to be able to write something like

f(x) = some_stuff(a,b,c)

and have Python, instead of complaining about undeclared identifiers or attempting to invoke the function some_stuff, convert it to a literal expression for my further convenience.

It is possible to get a reasonable approximation to this by creating a class with properly redefined __getattr__ and __setattr__ methods and use it as follows:

e = Expression()
e.f[e.x] = e.some_stuff(e.a, e.b, e.c)

It would be cool though, if it were possible to get rid of the annoying "e." prefixes and maybe even avoid the use of []. So I was wondering, is it possible to somehow temporarily "redefine" global name lookups and assignments? On a related note, maybe there are good packages for easily achieving such "quoting" functionality for Python expressions?


Solution

  • I'm not sure it's a good idea, but I thought I'd give it a try. To summarize:

    class PermissiveDict(dict):
        default = None
    
        def __getitem__(self, item):
            try:
                return dict.__getitem__(self, item)
            except KeyError:
                return self.default
    
    def exec_with_default(code, default=None):
        ns = PermissiveDict()
        ns.default = default
        exec code in ns
        return ns