views:

45

answers:

2

I use vars() function for the first time, and noticed this behaviour:

nodes = ['one', 'two', 'three']

for node in nodes:
    vars()[node + '_'] = 'some calc ' + node
    vars()[node] = vars()[node + '_']

print one

With this snippet Python outputs some calc one as expected, but if I use it inside function like this:

def main():

    nodes = ['one', 'two', 'three']

    for node in nodes:
        vars()[node + '_'] = 'some calc ' + node
        vars()[node] = vars()[node + '_']

    print one

main()

it outputs NameError: global name 'one' is not defined

vars() object is dict:

{'node': 'three', 'three_': 'some calc three', 'two': 'some calc two', 'one': 'some calc one', 'two_': 'some calc two', 'three': 'some calc three', 'nodes': ['one', 'two', 'three'], 'one_': 'some calc one'}

Now, I would like to know what's going on as this function is not well documented and I can't find example how to return those variables if inside function

A: 

vars() acts like locals() if called with no args, so from the docs:

Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.

Ignacio Vazquez-Abrams
+1  A: 

The reason that it works when called in a modules 'global' scope, is that it is equivalent to globals() in that context which is actually a dictionary stored by python. The locals of non-global scopes are not actually a dictionary in the implementation, (this is to avoid having to lookup dictionary keys when accessing them) and so there is no real dictionary to return. Instead, Python makes one up for you but it is not in any way connected to the real array of local variables. The only way that I know of to insert new locals into an executing frame is to use exec or eval but there is almost always a better way to do what you want that doesn't involve creating locals on the fly.

If you want to create locals in a non-executing frame, then you can apply bytecode transformations to it to, e.g. turn globals into locals, cells or constants but that is some non-trivial black magic and, again, there is almost certainly a better way.

Your question makes reference to returning things but I don't see anything that you are returning. What exactly do you want to return?

I would thing that the name that you give your return values should have very little impact as this is not the name that they will be given in the calling frame. Why doesn't a simple dictionary suffice?

aaronasterling
Thanks for explanations. I wanted names to be kept this way as they simplify code to my limited Python knowledge. I'm trying to parse Google Books response (i.e. link: http://www.google.com/books/feeds/volumes/g__6DX33JWUC) which I have in xml_data variable and pass it for additional processing. Here is that function - (link: http://codepad.org/ne4jZQ3k) Of course I could extend the code, but this approach seemed fine to me
romor
PS: If not obvious I'm using lxml
romor