Question

J'ai une méthode dans mon code Python qui renvoie un tuple - une ligne d'une requête SQL.Disons qu'il comporte trois champs :(jobId, étiquette, nom d'utilisateur)

Pour faciliter le transfert entre les fonctions, j'ai transmis l'intégralité du tuple en tant que variable appelée « job ».Cependant, au final, je veux en savoir plus, j'utilise donc un code comme celui-ci :(jobId, label, nom d'utilisateur) = travail

J'ai cependant réalisé qu'il s'agissait d'un cauchemar de maintenance, car désormais je ne pourrai plus jamais ajouter de nouveaux champs au jeu de résultats sans casser tout mon code existant.Comment aurais-je dû écrire cela ?

Voici mes deux meilleures suppositions :(jobid, étiquette, nom d'utilisateur) = (Job [0], Job [1], Job [2]) ... mais cela ne s'évalent pas bien lorsque vous avez 15 ... 20 champs

ou pour convertir immédiatement les résultats de la requête SQL en un dictionnaire et le transmettre (je n'ai aucun contrôle sur le fait qu'il commence sa vie en tant que tuple, c'est corrigé pour moi)

Était-ce utile?

La solution

Je dirais qu'un dictionnaire est certainement la meilleure façon de le faire.Il est facilement extensible, vous permet de donner à chaque valeur un nom sensé et Python possède de nombreuses fonctionnalités de langage intégrées pour utiliser et manipuler des dictionnaires.Si vous devez ajouter d'autres champs ultérieurement, il vous suffit de modifier le code qui convertit le tuple en dictionnaire et le code qui utilise réellement les nouvelles valeurs.

Par exemple:

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

Autres conseils

@Staale

Il y a un meilleur moyen:

job = dict(zip(keys, values))

C'est une vieille question, mais...

Je suggère d'utiliser un tuple nommé dans cette situation : collections.namedtuple

Voici en particulier la partie qui vous sera utile :

Le sous-classement n'est pas utile pour ajouter de nouveaux champs stockés.Au lieu de cela, créez simplement un nouveau type de tuple nommé à partir de l'attribut _fields.

C'est peut-être exagéré pour votre cas, mais je serais tenté de créer une classe "Job" qui prend le tuple comme argument constructeur et possède des propriétés respectives.Je ferais alors circuler des instances de cette classe à la place.

J'utiliserais un dictionnaire.Vous pouvez convertir le tuple en dictionnaire de cette façon :

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

Cela créera d'abord un tableau [["jobid", val1], ["label", val2], ["username", val3]], puis le convertira en dictionnaire.Si l'ordre ou le nombre des résultats change, il vous suffit de modifier la liste des clés pour qu'elle corresponde au nouveau résultat.

PS encore frais sur Python moi-même, donc il pourrait y avoir de meilleures façons de procéder.

Une vieille question, mais comme personne ne l'a mentionnée, j'ajouterai ceci à partir du Python Cookbook :

Recette 81252 :Utilisation de dtuple pour un accès flexible aux résultats de requête

Cette recette est spécialement conçue pour traiter les résultats de la base de données, et la solution dtuple vous permet d'accéder aux résultats par nom OU numéro d'index.Cela évite d'avoir à accéder à tout par indice, ce qui est très difficile à maintenir, comme indiqué dans votre question.

Avec un tuple, il sera toujours compliqué d'ajouter ou de modifier des champs.Vous avez raison, un dictionnaire serait bien meilleur.

Si vous voulez quelque chose avec une syntaxe légèrement plus conviviale, vous voudrez peut-être jeter un œil aux réponses cette question à propos d'un simple objet "de type struct".De cette façon, vous pouvez faire circuler un objet, par exemple job, et accédez à ses champs encore plus facilement qu'un tuple ou un dict :

job.jobId, job.username = jobId, username

Si vous utilisez le package MySQLdb, vous pouvez configurer vos objets curseur pour qu'ils renvoient des dictionnaires au lieu de tuples.

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 dis-tu de ça:

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

Vous pourriez alors faire :

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

Ça devrait être facile à échanger self.fieldlist.index(field) avec une recherche dans le dictionnaire plus tard...modifiez simplement votre __init__ méthode!Quelque chose comme le fait Staale.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top