Alexz Alexz - 5 months ago 7x
Python Question

How to retrieve a value from an executed string?

I didn't quite know how to word my question as this isn't something one would often do.
Here's my situation:

I have a list of values.

Values= ["1","2","3","4"]

I then want to be able to separately access each of the values and combine them into a string with commas in between them. I wrote a bit of code that I want to format a string ('{}'.format())in such a way so that the outcome looks like this: '1,2,3,4'. My code that I have so far (it is also the code structure that I'd prefer to use if possible) is the following:

string = "{}".format(exec(
"Out= ''\n"
"for value in Values:\n"
" Out+= value + ','\n"

If, within the string that is given as the parameter to the 'exec' function, I write "print(Out)"

string = "{}".format(exec(
"Out= ''\n"
"for value in Values:\n"
" Out+= value + ','\n"

Then the program will properly run and print out "1,2,3,4", but it will not store it in 'string' (Which is to be expected)

I therefore thought of adding a function in order to make sure that it can return something. I wrote the following, but as expected it also didn't work. string is still None:

string = "{}".format(exec(
"def do_stuff():\n"
" Out = ''\n"
" for value in Values :\n"
" Out += value + ','\n"
" return Out \n"

Now, I do realise that this method of combining strings is nowhere near the preferred way to combine strings, but let me give you some context.

I am making a game in python. There is a Character class and it contains various attributes of various data types (such as dict, list, int, str, float.... as well as some custom ones: AI, Item, ActiveSkill, PassiveSkill, Effect, Weapon, Armour etc...)
Now, my plan is to be able to store the game progress in a json tree. For that I started giving each of these entities a method which will convert all of its attributes into json trees stored as strings. That way, when I want to save the game and it comes to the Character, it will sort all of its attributes, but it'll also have to make a call to objects that it's referencing (such as ActiveSkills). For each of ActiveSkills in a list, it'll have to call for their own json syntaxed strings and combine these using commas.

Here's some of my code to help you understand what I want to do:

json += \
'"ActiveSkills":[{oActiveSkills}],' \
'"PassiveSkills":[{oPassiveSkills}].' \
"Skills = ''\n"
"for skill in self.ActiveSkills:\n" # ActiveSkills is a list of ActiveSkill objects
" Skills+=skill.encode_to_json() + ','\n"
"return Skills"),
"Skills = ''\n"
"for skill in self.PassiveSkills:\n" # PassiveSkills is a list of PassiveSkill objects
" Skills+=skill.encode_to_json() + ','\n"
"return Skills"),
"Effects = ''\n"
"for effect in self.Effects:\n" # Effects is a list of Effect objects
" Effects+=effect.encode_to_json() + ','\n"
"return Effects"))

I know that this code currently doesn't run, as you can only return from within a function, but I really don't know how to go about it in a quick and easy way.

One solution that I have saved up as a last resort is to just do everything by hand. IE: Have some kind of for loop that creates a string from returned values. Add this string to the json string, after which you will manually open and close with "},{" and make sure that there isn't a "," at the end. Then repeat this for PassiveSkills and Effects also. Finally, close the json string with "}," and add it to the 'json' (string type) variable...

I want to minimise the space taken up by this, and I want this system to be flexible, so that no matter how many skills in a list that you have, you could continue adding more and more of these json strings without changing the code.


To join a list using ',':

Values = ["1","2","3","4"]
result = ",".join( Values )

More info about str.join(iterable)can be found here in the online documentation.

For a better solution to store dictionaries and lists (and, using pickle, objects), you should look at the json and pickle packages in the Python Standard Library.

For example, with json:

import json

mydata = {}
mydata['hello'] = { 'value1':1, 'valuuelist':[1,2,3,4] }



{"hello": {"valuuelist": [1, 2, 3, 4], "value1": 1}}

So, don't roll your own encoder, unless you really have to.