2013-07-18 12 views
7

ho una tupla che elenca i metodi di una classe come:dinamica metodo di chiamata In Python 2.7 usando stringhe di nomi di metodo

t = ('methA','methB','methC','methD','methE','methF') 

e così via ..

Ora ho bisogno di chiamare in modo dinamico questi metodi basati su una selezione fatta dall'utente. I metodi devono essere chiamati in base all'indice. Quindi, se un utente seleziona "0", viene chiamato methA, se "5" viene chiamato methF.

Il mio metodo per fare questo è la seguente:

def makeSelection(self, selected): 
    #methodname = t[selected] 
    #but as this is from within the class , it has to be appended with 'self.'methodname 
    # also need to pass some arguments locally calculated here 

Sono riuscito a lavorare fuori qualcosa con eval ma cede di errore e non è affatto elegante.

risposta

19

Se si sta chiamando un metodo su un oggetto (inclusi i moduli importati) è possibile utilizzare:

getattr(obj, t[i])(*args) 

Se è necessario chiamare una funzione nel modulo corrente

getattr(sys.modules[__name__], t[i])(*args) 

dove args è una lista o una tupla di argomenti da inviare, o puoi semplicemente elencarli nella chiamata come faresti con qualsiasi altra funzione. Dato che sei in un metodo cercando di chiamare un altro metodo sullo stesso oggetto, utilizzare la prima con self al posto di obj

getattr prende un oggetto e una stringa, e fa una ricerca attributo nell'oggetto, restituendo l'attributo se esiste obj.x e getattr(obj, 'x') ottengono lo stesso risultato. Ci sono anche le funzioni setattr, e delattr se si desidera approfondire questo tipo di riflessione.



Un approccio completamente alternativo:
Dopo aver notato la quantità di attenzione questa risposta ha ricevuto, ho intenzione di suggerire un approccio diverso a quello che stai facendo. Darò per scontato alcuni metodi esistono

def methA(*args): print 'hello from methA' 
def methB(*args): print 'bonjour de methB' 
def methC(*args): print 'hola de methC' 

Per rendere ogni metodo corrisponde a un numero (selezione) Costruisco un dizionario numeri di mappatura ai metodi stessi

id_to_method = { 
    0: methA, 
    1: methB, 
    2: methC, 
} 

Detto questo, sarebbe id_to_method[0]() richiamare methA. Sono due parti, la prima è id_to_method[0] che ottiene l'oggetto funzione dal dizionario, quindi lo chiama (). Potrei anche passare argomento id_to_method[0]("whatever", "args", "I", "want) Nel codice vero e proprio, per quanto precede si sarebbe probabilmente avere qualcosa come

choice = int(raw_input('Please make a selection')) 
id_to_method[choice](arg1, arg2, arg3) # or maybe no arguments, whatever you want 
+0

Cosa sarebbe una bella soluzione se noi stavamo considerando metodi di istanza? Ad esempio: immagina che i metodi che hai scritto ora includano l'argomento autonomo: def methA (self, * args): stampa 'ciao da methA' ma vorrei costruire il dizionario nella classe (in modo che le chiavi possano essere lette senza necessariamente avere un'istanza) e non nel costruttore. Come si potrebbe farlo? – marcotama

+0

È possibile utilizzare metodi non associati e 'getattr' in modo analogo come qui. Non sono sicuro di capire quello che vuoi. –

+0

Gli oggetti della mia classe X hanno metodi alternativi di "esplorazione". La funzione y si interfaccia con l'utente e chiama il metodo di esplorazione desiderato. Piuttosto che avere if-elif-elif -... Preferirei accedere ad un dizionario perché sembra migliore. Inoltre, se il dizionario fosse una variabile di classe, potrei accedere alle sue chiavi dall'esterno. Il problema qui è che questi metodi di esplorazione dipendono da variabili d'istanza. Ho anche pensato (e implementato) il trucco 'getattr', ma non sembra affatto carino. – marcotama

Problemi correlati