Вызов кода в строке без exec / eval, python - PullRequest
5 голосов
/ 11 августа 2010

У меня есть этот код, который выполняется, когда игрок пытается что-то съесть:

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

и этот код для предметов (обрезается)

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?')"
    }
}

Существует ли допустимый способ вызоваэлементы [что угодно] ['on_eat'], не делая глупостей, таких как exec () или eval ()?Если нет, альтернативное форматирование в качестве примера также будет приветствоваться.

До этого значения items [everyitems] ['on_eat'] не были строками, но выполняли on_eat для каждого элемента, как только код былпобежал.

Я видел много ответов на подобные вопросы, но они не имеют дело с аргументами для уникальных функций - проще говоря, они были больше похожи на this

Ответы [ 3 ]

6 голосов
/ 11 августа 2010

Вы можете сохранить свою функцию и аргументы функции как 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.'
1 голос
/ 11 августа 2010

Вы можете использовать кодовый модуль

def eat(target='object'):
    import code
    console = code.InteractiveConsole(locals()) # make a python interpreter with local vars
    if target in inventory:
        console.push("items[target]['on_eat']")
    else:
        print 'You have no ' + target + ' to eat.'
0 голосов
/ 11 августа 2010

Альтернативой частичным функциям является написание таких элементов

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?',))
    }
}

и вызов их так

def eat(target='object'):
    if target in inventory:
        func, args = items[target]['on_eat']
        func(*args)
    else:
        print 'You have no ' + target + ' to eat.'

Вам не нужны эти global операторы, если только выбудет переназначать их

...