Python __setattr__ and __getattr__ for global scope?

Suppose I need to create my own little DSL that Python will use to describe a specific data structure. For instance. I would like to write something like

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

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

You can get a reasonable approximation of this by creating a class with correctly overridden methods __getattr__ and __setattr__ and using it as follows:

 e = Expression() ef[ex] = e.some_stuff(ea, eb, ec) 

It would be great if we could get rid of the annoying e. prefixes and perhaps even avoid using []. Therefore, I was wondering, is it possible to somehow temporarily β€œredefine” global search queries and destinations? In the corresponding note, maybe there are good packages to easily achieve such β€œciting” functionality for Python expressions?

+4
source share
3 answers

I'm not sure this is a good idea, but I thought I would try . Summarizing:

 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 
+3
source

You might want to take a look at the ast or parser modules that are part of Python for parsing, accessing, and transforming the abstract syntax tree (or syntax tree) of the input code. As far as I know, the Sage math system written in Python has a similar pre-compiler.

+2
source

In response to Wai's comment, here is one interesting solution that I found. First of all, to explain again what it does, suppose you have the following code:

 definitions = Structure() definitions.add_definition('f[x]', 'x*2') definitions.add_definition('f[z]', 'some_function(z)') definitions.add_definition('g.i', 'some_object[i].method(param=value)') 

where adding definitions involves parsing the left side and the right side and doing other ugly things. Now one (not necessarily good, but certainly funny) approach would allow writing the code above as follows:

 @my_dsl def definitions(): f[x] = x*2 f[z] = some_function(z) gi = some_object[i].method(param=value) 

and Python does most of the parsing under the hood. The idea is based on a simple statement exec <code> in <environment> mentioned by Jan, with one hacker addition. Namely, the byte code of the function should be slightly changed, and all operations with local variable access (LOAD_FAST) switched to variable access from the environment (LOAD_NAME).

This is easier than explained: http://fouryears.eu/wp-content/uploads/pydsl/

There are various tricks you can do to make them practical. For example, in the code provided by the link above, you cannot use the built-in functions and language constructs, for example, for loops and if statements in the @my_dsl function. However, you can make them work by adding more behavior to the Env class.

Update Here is a slightly more detailed explanation of the same.

-1
source

Source: https://habr.com/ru/post/1307200/


All Articles