2010-08-11 6 views
5

Je le code qui exécute quand un joueur tente de manger quelque chose:Indicatif téléphonique dans une chaîne sans exec/eval, python

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

et ce code pour les éléments (coupé)

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

Existe-t-il un moyen valide d'appeler items [whatever] ['on_eat'] sans faire quelque chose de stupide comme exec() ou eval()? Sinon, un formatage alternatif à titre d'exemple serait également apprécié. Avant cela, les valeurs des éléments [everyitems] ['on_eat'] n'étaient pas des chaînes, mais exécutaient l'on_eat pour chaque élément dès que le code était exécuté.

J'ai vu beaucoup de réponses à des questions similaires, mais ils ne traitent pas des arguments pour les fonctions afin de mieux mettre unique-, ils étaient plus comme this

Répondre

6

Vous pouvez stocker vos arguments de la fonction et la fonction comme 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

C'est étrange; Ça marche. Eh bien, je suppose que c'est logique, pouvez-vous/quelqu'un me dire comment cela descend vitesse/cpu/étapes sage? Aussi, pourquoi les partiels ne s'exécutent-ils pas au hasard une fois que les éléments sont définis comme quand les valeurs des items [blah] ['on_eat'] étaient "" less/normal des appels de fonction? –

+0

Parce que le partiel ne fait pas * appeler * la fonction lorsque le partiel est créé dans les éléments on_eat de vos items dict. Tout ce qu'il fait est de capturer la fonction à appeler et tous les arguments pour l'appeler. La fonction est appelée lorsque vous accédez au partial et l'appelle with(). Essayez ceci: z = partiel (min, 2, 4, 6) Rien ne se passe. Maintenant appelez z: z() Vous obtenez la réponse 2. min n'a pas été appelé lorsque le partiel a été créé; il n'a été appelé que lorsque vous avez appelé le partiel en tant que z(). Speedwise, il devrait être assez proche de la même chose que d'appeler la fonction d'origine. – PaulMcG

+0

Merci. Aussi, que faire si je veux faire plusieurs choses à la fois avec des articles ['alimentation de transport magique de Dante \' s Inferno '] [' on_eat '] qui imprime, change current_room, appelle normal_eat, imprime à nouveau, explose les utilisateurs haut-parleurs, ect. Je suppose que je devrais faire une fonction séparée qui fait tout cela? –

1

vous pouvez utiliser le module de code

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

désolé j'ai manqué une citation de fermeture après l'objet – user250418

+2

bien alors l'éditer! – aaronasterling

0

Une alternative aux fonctions partielles est d'écrire des articles lik e ce

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

et l'appeler comme ça

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

Vous n'avez pas besoin il y a ces déclarations global à moins que vous leur réaffectant

Questions connexes