2008-09-03 13 views
12

Tengo un método en mi código Python que devuelve una tupla, una fila de una consulta SQL. Digamos que tiene tres campos: (Id. De trabajo, etiqueta, nombre de usuario)Partición de tuplas en Python: ¿práctica recomendada?

Para facilitar el paso de una función a otra, he estado pasando toda la tupla como una variable llamada 'trabajo'. Eventualmente, sin embargo, quiero llegar a los bits, así que he estado usando un código como este: (jobId, etiqueta, nombre de usuario) = trabajo

Me he dado cuenta, sin embargo, de que esto es una pesadilla de mantenimiento, porque ahora nunca puedo agregar nuevos campos al conjunto de resultados sin romper todo mi código existente. ¿Cómo debería haber escrito esto?

Éstos son mis dos mejores conjeturas: (jobId, etiqueta, nombre de usuario) = (trabajo [0], el trabajo [1], el trabajo [2]) ... pero eso no escala bien cuando se tiene 15 ... 20 campos

o convertir los resultados de la consulta SQL a un diccionario de inmediato y pasarlo de largo (no tengo control sobre el hecho de que empieza a funcionar como una tupla, eso está arreglado para mí)

Respuesta

13

Yo diría que un diccionario es definitivamente la mejor manera de hacerlo. Es fácilmente extensible, le permite dar a cada valor un nombre razonable, y Python tiene muchas características de lenguaje integradas para usar y manipular diccionarios. Si necesita agregar más campos más adelante, todo lo que necesita cambiar es el código que convierte la tupla en un diccionario y el código que realmente usa los nuevos valores.

Por ejemplo:

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

vea también http://code.activestate.com/recipes/81252/ – Jay

0

Con una tupla que siempre habrá una molestia para añadir o cambiar los campos. Tienes razón en que un diccionario será mucho mejor.

Si desea algo con sintaxis levemente más amigable, es posible que desee consultar las respuestas this question sobre un objeto simple 'struct-like'. De esa manera se puede pasar alrededor de un objeto, por ejemplo job, y acceder a sus campos, incluso con más facilidad que una tupla o dict:

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

Tal vez esto es demasiado para su caso, pero me gustaría tener la tentación de crear un "empleo "clase que toma la tupla como su argumento de constructor y tiene propiedades respectivas sobre ella. En su lugar, pasaría instancias de esta clase.

2

Yo usaría un diccionario. Puede convertir la tupla a un diccionario de esta manera:

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

Este primer creará una matriz [[ "jobid", val1], [ "etiqueta", val2], [ "nombre de usuario", val3]] y luego conviértalo a un diccionario. Si el orden o conteo de resultados cambia, solo necesita cambiar la lista de claves para que coincida con el nuevo resultado.

PD todavía estoy fresco en Python, por lo que podría haber mejores formas de hacerlo.

+2

Vea la respuesta de Aaron Maenpaa de Zip. Un error común de principiante en Python es utilizar la comprensión de listas cuando el zip sea suficiente. –

-2

¿Qué tal esto:

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

A continuación, podría hacer:

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

Debe ser fácil de cambiar self.fieldlist.index(field) con una búsqueda de diccionario más adelante ...¡solo edite su método __init__! Algo como Staale hace.

13

@Staale

Hay una mejor manera:

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

Este es también un código muy fácil de mantener, el único "problema" es reconstruir el código para tratar con diccionarios. –

2

Una cuestión de edad, pero como nadie lo mencionó Voy a añadir esto desde el libro de cocina de Python:

Recipe 81252: Using dtuple for Flexible Query Result Access

Esta receta está diseñada específicamente para tratar los resultados de la base de datos, y la solución dtuple le permite acceder a los resultados por nombre O número de índice. Esto evita tener que acceder a todo mediante un subíndice que es muy difícil de mantener, como se indica en su pregunta.

5

Ésta es una vieja pregunta, pero ...

me gustaría sugerir el uso de una tupla nombrado en esta situación: collections.namedtuple

Esta es la parte en particular que te gustaría encontrar útil:

La subclasificación no es útil para agregar nuevos campos almacenados. En su lugar, simplemente cree un nuevo tipo de tupla con nombre del atributo _fields.

+2

Otros beneficios: el enfoque * namedtuple * usa menos memoria que un diccionario y admite un método \ _replace() para actualizar los valores. –

+0

Técnicamente, '_replace()' crea una nueva tupla con los valores reemplazados, ya que las instancias de las clases 'namedtuple' son inmutables como las tuplas regulares. – JAB

0

Si está utilizando el paquete MySQLdb, puede configurar los objetos del cursor para que devuelvan los dicts en lugar de las tuplas.

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 
Cuestiones relacionadas