Pregunta

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)

Para facilitar su transferencia entre funciones, he estado pasando la tupla completa como una variable llamada "trabajo".Sin embargo, eventualmente quiero llegar a los bits, así que he estado usando un código como este:(jobId, etiqueta, nombre de usuario) = trabajo

Sin embargo, me di cuenta 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?

Aquí están mis dos mejores conjeturas:(jobId, etiqueta, nombre de usuario) = (trabajo[0], trabajo[1], trabajo[2]) ... Pero eso no escala bien cuando tienes 15...20 campos

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

¿Fue útil?

Solución

Yo diría que un diccionario es definitivamente la mejor manera de hacerlo.Es fácilmente extensible, le permite darle a cada valor un nombre sensato 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 utiliza los nuevos valores.

Por ejemplo:

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

Otros consejos

@staale

Hay una mejor manera:

job = dict(zip(keys, values))

Esta es una vieja pregunta, pero...

Sugeriría usar una tupla con nombre en esta situación: colecciones.namedtuple

Esta es la parte, en particular, que le resultará útil:

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

Quizás esto sea excesivo para su caso, pero estaría tentado a crear una clase "Trabajo" que tome la tupla como argumento constructor y tenga las propiedades respectivas.Luego, en su lugar, pasaría instancias de esta clase.

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

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

Esto primero creará una matriz [["jobid", val1], ["label", val2], ["username", val3]] y luego la convertirá en un diccionario.Si el orden de los resultados o el recuento 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 maneras de hacer esto.

Una vieja pregunta, pero como nadie la mencionó, agregaré esto del Libro de cocina de Python:

Receta 81252:Uso de dtuple para acceso flexible a resultados de consultas

Esta receta está diseñada específicamente para manejar resultados de bases 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 por subíndice, lo cual es muy difícil de mantener, como se indica en su pregunta.

Con una tupla siempre será complicado agregar o cambiar campos.Tienes razón en que un diccionario será mucho mejor.

Si desea algo con una sintaxis un poco más amigable, puede echar un vistazo a las respuestas. esta pregunta sobre un objeto simple 'similar a una estructura'.De esa manera puedes pasar un objeto, digamos job, y acceder a sus campos incluso más fácilmente que una tupla o un dict:

job.jobId, job.username = jobId, username

Si está utilizando el paquete MySQLdb, puede configurar los objetos del cursor para que devuelvan dictados en lugar de 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

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)]

Entonces podrías hacer:

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

Debería ser fácil de intercambiar self.fieldlist.index(field) con una búsqueda en el diccionario más adelante...solo edita tu __init__ ¡método!Algo parecido a lo que hace Staale.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top