2008-09-03 16 views
12

Ho un metodo nel mio codice Python che restituisce una tupla - una riga da una query SQL. Diciamo che ha tre campi: (jobId, label, username)Dividere le tuple in Python - best practice?

Per facilitare il passaggio tra le funzioni, ho passato l'intera tupla come variabile chiamata "job". Alla fine, comunque, voglio ottenere i bit, quindi ho usato un codice come questo: (jobId, label, username) = job

Ho capito, tuttavia, che questo è un incubo di manutenzione, perché ora non posso mai aggiungere nuovi campi al set di risultati senza rompere tutto il mio codice esistente. Come avrei dovuto scrivere questo?

Qui sono i miei due migliori ipotesi: (jobId, etichetta, nome utente) = (lavoro [0], lavoro [1], di posti di lavoro [2]) ... ma che non scala bene quando si hanno 15 ... 20 campi

o per convertire i risultati dalla query SQL in un dizionario immediatamente e passare tale intorno (non ho il controllo sul fatto che inizia vita come una tupla, che è stato risolto per me)

risposta

13

Direi che un dizionario è sicuramente il modo migliore per farlo. È facilmente estensibile, consente di assegnare a ciascun valore un nome ragionevole e Python dispone di molte funzionalità del linguaggio incorporate per l'utilizzo e la manipolazione dei dizionari. Se è necessario aggiungere più campi in seguito, tutto ciò che è necessario modificare è il codice che converte la tupla in un dizionario e il codice che utilizza effettivamente i nuovi valori.

Ad esempio:

job={} 
job['jobid'], job['label'], job['username']=<querycode> 
+0

vedere anche http://code.activestate.com/recipes/81252/ – Jay

0

Con una tupla sarà sempre una seccatura per aggiungere o modificare i campi. Hai ragione che un dizionario sarà molto meglio.

Se si desidera qualcosa con una sintassi leggermente più amichevole, si potrebbe voler dare un'occhiata alle risposte this question su un semplice oggetto "simile a una struttura". In questo modo è possibile passare intorno ad un oggetto, dicono job e accedere i suoi campi ancora più facilmente di una tupla o dict:

job.jobId, job.username = jobId, username 
3

Forse questo è eccessivo per il vostro caso, ma sarei tentato di creare un "Job "classe che prende la tupla come argomento del costruttore e ha le rispettive proprietà su di esso. Poi passerei invece le istanze di questa classe.

2

Vorrei usare un dizionario. È possibile convertire il tuple a un dizionario in questo modo:

values = <querycode> 
keys = ["jobid", "label", "username"] 
job = dict([[keys[i], values [i]] for i in xrange(len(values))]) 

Questo sarà prima creare un array [[ "jobid", val1], [ "etichetta", val2], [ "username", val3]] e quindi convertirlo in un dizionario. Se l'ordine o il conteggio dei risultati cambia, è sufficiente modificare l'elenco di chiavi per far corrispondere il nuovo risultato.

PS ancora da solo su Python, quindi potrebbero esserci modi migliori per farlo.

+2

Vedere Aaron Maenpaa risposta di Zip. Un comune errore newbie in Python sta usando la comprensione delle liste quando zip sarà sufficiente. –

-2

ne dite di questo:

class TypedTuple: 
    def __init__(self, fieldlist, items): 
     self.fieldlist = fieldlist 
     self.items = items 
    def __getattr__(self, field): 
     return self.items[self.fieldlist.index(field)] 

È quindi possibile fare:

j = TypedTuple(["jobid", "label", "username"], job) 
print j.jobid 

Dovrebbe essere facile scambiare self.fieldlist.index(field) con una consultazione dei dizionari più tardi ...basta modificare il tuo metodo __init__! Qualcosa come lo fa Staale.

13

@Staale

C'è un modo migliore:

job = dict(zip(keys, values)) 
+0

Questo è anche un codice molto manutenibile, l'unico "problema" è la ricostruzione del codice per gestire i dizionari. –

2

una vecchia questione, ma dal momento che nessuno ha menzionato che io aggiunga questo dal Python Cookbook:

Recipe 81252: Using dtuple for Flexible Query Result Access

Questa ricetta è progettata specificamente per gestire i risultati del database e la soluzione dtuple consente di accedere ai risultati per nome O numero di indice. Ciò evita di dover accedere a tutto tramite un indice che è molto difficile da mantenere, come indicato nella domanda.

5

Questa è una vecchia questione, ma ...

Io suggerirei usando una tupla di nome in questa situazione: collections.namedtuple

questa è la parte, in particolare, che si può trovare utile:

La sottoclasse non è utile per aggiungere nuovi campi memorizzati. Invece, crea semplicemente un nuovo tipo di tupla dall'attributo _fields.

+2

Altri vantaggi: l'approccio * namedtuple * utilizza meno memoria di un dizionario e supporta un metodo \ _replace() per l'aggiornamento dei valori. –

+0

Tecnicamente, '_replace()' crea una nuova tupla con i valori sostituiti, poiché le istanze delle classi 'namedtuple' sono immutabili proprio come le normali tuple. – JAB

0

Se si utilizza il pacchetto MySQLdb, è possibile impostare gli oggetti del cursore per restituire dic invece che tuple.

import MySQLdb, MySQLdb.cursors 
conn = MySQLdb.connect(..., cursorclass=MySQLdb.cursors.DictCursor) 
cur = conn.cursor() # a DictCursor 
cur2 = conn.cursor(cursorclass=MySQLdb.cursors.Cursor) # a "normal" tuple cursor