2010-08-11 8 views
5

Ho questo codice che viene eseguito quando un giocatore tenta di mangiare qualcosa:Chiamata del codice in una stringa senza 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.' 

e questo codice per gli elementi (tagliati)

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

C'è un modo valido per chiamare gli oggetti [qualunque cosa] ['on_eat'] senza fare qualcosa di stupido come exec() o eval()? In caso contrario, sarebbe apprezzata anche la formattazione alternativa come esempio.

Prima di ciò i valori [everyitems] ['on_eat'] degli elementi non erano stringhe, ma che eseguivano l'on_eat per ogni voce non appena veniva eseguito il codice.

ho visto molte risposte a domande simili, ma loro non si occupano di argomenti per le funzioni unique- di mettere meglio che, erano più come this

risposta

6

È possibile memorizzare la funzione e la funzione argomenti come 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

Questo è strano; Funziona. Beh, suppongo che abbia senso, puoi/qualcuno dirmi come questo scende velocità/cpu/passi saggi? Inoltre, perché i partial non vengono eseguiti casualmente una volta che gli oggetti sono definiti come quando i valori degli articoli [blah] ['on_eat'] erano "" chiamate di funzione meno/normali? –

+0

Poiché il partial in realtà non * chiama * la funzione quando il partial viene creato negli elementi on_eat degli elementi dettati. Tutto ciò che fa è catturare la funzione da chiamare e gli eventuali argomenti con cui chiamarla. La funzione viene chiamata quando si accede al partial e lo si chiama con(). Prova questo: z = partial (min, 2, 4, 6) Non succede nulla. Ora chiama z: z() Si ottiene la risposta 2. Il min non è stato chiamato quando è stato creato il partial; è stato chiamato solo quando hai invocato il partial come z(). In senso orario, dovrebbe essere abbastanza vicino allo stesso come solo chiamando la funzione originale. – PaulMcG

+0

Grazie. Inoltre, cosa succede se voglio fare più cose contemporaneamente con elementi ['trasporto magico di cibo da Dante \' Inferno '] [' on_eat '] che stampa, cambia current_room, chiama normal_eat, stampa di nuovo, fa esplodere gli altoparlanti degli utenti, ecc. Suppongo che dovrei fare una funzione separata che fa tutto questo? –

1

è possibile utilizzare il modulo di codice

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

scusa ho perso una citazione di chiusura dopo l'oggetto – user250418

+2

bene quindi modificarlo! – aaronasterling

0

un'alternativa alle funzioni parziali è quello di scrivere articoli lik e questo

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

e chiamare in questo modo

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

Non hai bisogno di quelle dichiarazioni global lì a meno che non vi sarà riassegnando loro