2010-08-11 1 views
5

У меня есть этот код, который выполняется, когда игрок пытается съесть что-нибудь:телефонный код в виде строки без ехес/Eval, питон

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

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

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

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

ответ

6

Вы можете хранить свои функции и функции аргументы как 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.' 
+0

Это странно; Оно работает. Ну, я полагаю, это имеет смысл, можете ли вы/кто-нибудь сказать мне, как это снижается скорость/процессор/шаги мудрые? Кроме того, почему частичные операции не выполняются случайно, как только элементы определяются, например, когда значения пунктов [blah] ['on_eat'] были «меньше»/«нормальные» вызовы функций? –

+0

Поскольку частичное на самом деле не * вызывает * функцию, когда частичное создается в элементах on_eat ваших элементов dict. Все, что он делает, - это захват вызываемой функции и любых аргументов для ее вызова. Функция вызывается, когда вы получаете доступ к частичной части и вызываете ее с помощью(). Попробуйте это: z = partial (min, 2, 4, 6) Ничего не происходит. Теперь вызовите z: z() Вы вернете ответ 2. min не был вызван, когда частичное было создано; он вызывается только тогда, когда вы вызываете частичное как z(). Speedwise, это должно быть довольно близко к тому же, что и просто вызов оригинальной функции. – PaulMcG

+0

Спасибо. Кроме того, что, если я хочу сделать несколько вещей сразу с элементами ['магической транспортировки пищи из Dante \ Inferno'] ['on_eat'], который печатает, меняет current_room, вызывает normal_eat, снова печатает, взрывает динамиков пользователей и т. Д. Я предполагаю, что мне нужно будет сделать отдельную функцию, которая сделает все это? –

1

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

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

Извините, я пропустил заключительную цитату после объекта – user250418

+2

ну тогда отредактируйте его! – aaronasterling

0

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

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 заявления там, если не будет переназначение их