Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling code in a string without exec/eval, python

I have this code that executes when a player attempts to eat something:

def eat(target='object'):
    global current_room
    global locations
    global inventory
    if target in inventory:
        items[target]['on_eat'] #This is showing no results.
    else:
        print 'You have no ' + target + ' to eat.'

and this code for items(trimmed)

items = {
'strawberry': {
    'weight': 1,
    'text': 'The strawberry is red',
    'on_eat': "normal_eat('strawberry', 'pretty good, but not as sweet as you expected')"
    },
'trees': {
    'weight': 50,
    'text': 'The trees are tall with large, leaf filled branches blocking out a majority of sunlight.',
    'on_eat': "forcesay('Eating trees? What the hell is your problem?')"
    }
}

Is there a valid way of calling items[whatever]['on_eat'] without doing something silly like exec() or eval()? If not, alternative formatting as an example would also be appreciated.

Before this the items[everyitems]['on_eat'] values were not strings, but that executed the on_eat for every item as soon as the code was ran.

I have seen many answers to similar questions, but they don't deal with arguments for functions unique- to better put that, they were more like this

like image 352
mask_man Avatar asked Aug 11 '10 05:08

mask_man


People also ask

What can I use instead of eval in Python?

literal_eval may be a safer alternative. literal_eval() would only evaluate literals, not algebraic expressions.

How do I execute a string containing Python code in Python?

If you want to execute Python statements, you can use exec(string). For example, >>> my_code = 'print "Hello World!"' >>> exec(my_code) Hello World!

Why you shouldn't use eval in Python?

Since the eval() function will evaluate any Python expressions, the hacker can easily get a list of files and folders on the server. To be honest, you probably will be fired if the above string is really evaluated by the eval() function.


1 Answers

You can store your function and function arguments as a partial:

from functools import partial

items = { 
'strawberry': { 
    'weight': 1, 
    'text': 'The strawberry is red', 
    'on_eat': partial(normal_eat, 'strawberry', 'pretty good, but not as sweet as you expected') 
    }, 
'trees': { 
    'weight': 50, 
    'text': 'The trees are tall with large, leaf filled branches blocking out a majority of sunlight.', 
    'on_eat': partial(forcesay, 'Eating trees? What the hell is your problem?')
    } 

def eat(target='object'):  
    # those globals are probably not necessary
    if target in inventory:  
        items[target]['on_eat']()  #Add ()'s to call the partial
    else:  
        print 'You have no ' + target + ' to eat.'
like image 177
PaulMcG Avatar answered Sep 30 '22 03:09

PaulMcG