For my examine command, because I don't want to do this:
def examine(Decision):
if Decision == "examine sword":
print sword.text
elif Decision == "examine gold":
print gold.text
elif Decision == "examine cake":
print cake.text
...
for every item in my game.
So I wanted to convert the second word of the Decision string into a variable so that I could use something like secondwordvar.text.
I tried to use eval(), but I always get an errors when I make a spelling mistake in a single word command.
The error
IndexError: list index out of range
It's be working otherwise though.
Right now my code is this:
def exam(Decision):
try:
examlist = shlex.split(Decision)
useditem = eval(examlist[1])
print useditem.text
except NameError:
print "This doesn't exist"
Does anyone have an idea, for an other option, how I could write that function in a easy way?
I should probably also include the full game. You can find it here: http://pastebin.com/VVDSxQ0g
4 Answers 4
Somewhere in your program, create a dictionary mapping the name of the object to a variable that it represents. For example:
objects = {'sword': sword, 'gold': gold, 'cake': cake}
Then you can change your examine() function to something like the following:
def examine(Decision):
tokens = shlex.split(Decision)
if len(tokens) != 2 or tokens[0] != 'examine' or tokens[1] not in objects:
print "This doesn't exist"
else:
print objects[tokens[1]].text
1 Comment
What you could do (because with my knowledge in programming, somewhat limited, this is the most advanced way I could see it) is to utilize dictionaries. I'll try to explain in english, because my knowledge of code in this field is suspect and I don't want to mislead you.
Dictionaries are very array-like, allowing you to associate a decision with a value.
You would be able to associate Examine sword with an action code 4
This would (in a hack-y way) allow you to convert your string to a variable, more by direct and consistent referencing of key/value pairs.
Good luck with this approach; Read up some on Dictionaries and you may very well find them easier to handle than it sounds!
Finally, as a form of good coding practice, never use eval() unless you are sure of what you are doing. eval() executes the code inside the (), so if, god forbid, some malicious process manages to run that code with a malicious line injected inside it:
eval(###DELETE EVERYTHING RAWR###)
You'll have a bad time. Sincerely.
Also, for the sake of evaluating code, I've heard that it is a very slow command, and that there are better alternatives, performance-wise.
Happy coding!
1 Comment
Your variables are stored in a dictionary somewhere. If they are global variables, globals() returns this dictionary. You can use this to look up the variable by name:
globals()['sword'].text
If the variables are stored in a class as attributes, you can use getattr:
getattr(object, 'sword').text
You'll want to catch possible exceptions for bad names.
Comments
These two print the same text:
Using a dictionary:
texts = dict(sword = "wathever",
gold = "eachever",
cake = "whomever")
def examine_dict(decision):
decision = decision.split()[1]
print texts[decision]
examine_dict("examine sword")
Using object attributes (a class):
class Texts():
sword = "wathever"
gold = "eachever"
cake = "whomever"
def examine_attribute(decision):
decision = decision.split()[1]
text = getattr(Texts, decision)
print text
examine_attribute("examine sword")
Depending on what you want, one method can be more appropriate than the other. The dictionary-based method, however, is in general, the easier and the faster one.
eval. Your solution is correct (it just requires some more error handling), but F.J's is far cleaner / safer..correctly?examine smthng? I doubt this can lead to a good UX.