Calling code in a string without exec/eval, python
Question: 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](http://stackoverflow.com/questions/680941/python-dynamic-function-names
"this")


Answer: 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.'
    

