Pergunta

Eu tenho um método no meu código Python que retorna uma tupla - uma linha de uma consulta SQL.Digamos que tenha três campos:(jobId, rótulo, nome de usuário)

Para facilitar a passagem entre funções, passei a tupla inteira como uma variável chamada 'job'.Eventualmente, no entanto, quero chegar aos detalhes, então tenho usado um código como este:(jobId, rótulo, nome de usuário) = trabalho

Percebi, no entanto, que isso é um pesadelo de manutenção, porque agora nunca mais poderei adicionar novos campos ao conjunto de resultados sem quebrar todo o meu código existente.Como eu deveria ter escrito isso?

Aqui estão meus dois melhores palpites:(JobID, Label, nome de usuário) = (Job [0], Job [1], Job [2]) ... mas isso não escala bem quando você tem 15 ... 20 campos

ou para converter os resultados da consulta SQL em um dicionário imediatamente e repassá-los (não tenho controle sobre o fato de que ele começa como uma tupla, isso foi corrigido para mim)

Foi útil?

Solução

Eu diria que um dicionário é definitivamente a melhor maneira de fazer isso.É facilmente extensível, permite que você dê a cada valor um nome sensato e o Python possui muitos recursos de linguagem integrados para usar e manipular dicionários.Se precisar adicionar mais campos posteriormente, tudo o que você precisa alterar é o código que converte a tupla em um dicionário e o código que realmente faz uso dos novos valores.

Por exemplo:

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

Outras dicas

@Staale

Há um caminho melhor:

job = dict(zip(keys, values))

Essa é uma pergunta antiga, mas...

Eu sugeriria usar uma tupla nomeada nesta situação: coleções.namedtuple

Esta é a parte, em particular, que você acharia útil:

A subclasse não é útil para adicionar novos campos armazenados.Em vez disso, basta criar um novo tipo de tupla nomeado a partir do atributo _fields.

Talvez isso seja um exagero para o seu caso, mas eu ficaria tentado a criar uma classe "Job" que usasse a tupla como argumento do construtor e tivesse as respectivas propriedades.Em vez disso, eu passaria instâncias dessa classe.

Eu usaria um dicionário.Você pode converter a tupla em um dicionário desta forma:

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

Isso primeiro criará um array [["jobid", val1], ["label", val2], ["username", val3]] e depois o converterá em um dicionário.Se a ordem ou contagem dos resultados for alterada, você só precisará alterar a lista de chaves para corresponder ao novo resultado.

PS ainda estou atualizado em Python, então pode haver maneiras melhores de fazer isso.

Uma pergunta antiga, mas como ninguém a mencionou, acrescentarei isso do Python Cookbook:

Receita 81252:Usando dtuple para acesso flexível aos resultados da consulta

Esta receita foi projetada especificamente para lidar com resultados de banco de dados, e a solução dtuple permite acessar os resultados por nome OU número de índice.Isso evita ter que acessar tudo por subscrito que é muito difícil de manter, conforme observado na sua pergunta.

Com uma tupla sempre será um incômodo adicionar ou alterar campos.Você está certo ao dizer que um dicionário será muito melhor.

Se você quiser algo com uma sintaxe um pouco mais amigável, dê uma olhada nas respostas essa questão sobre um objeto simples 'semelhante a uma estrutura'.Dessa forma, você pode passar um objeto, digamos job, e acesse seus campos com ainda mais facilidade do que uma tupla ou ditado:

job.jobId, job.username = jobId, username

Se estiver usando o pacote MySQLdb, você pode configurar seus objetos cursor para retornar dictos em vez 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

Que tal agora:

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

Você poderia então fazer:

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

Deve ser fácil trocar self.fieldlist.index(field) com uma pesquisa no dicionário mais tarde ...basta editar o seu __init__ método!Algo como Staale faz.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top