2011-05-26 3 views
2

Python débutant ici. Une question sur les dictionnaires. Mon entrée est une liste de longueur variable (par exemple a = ['eggs', 'ham', 'bacon' ...]) qui fonctionne comme une liste de termes de recherche à utiliser sur un fichier CSV importé.Noms de variable avec dictionnaires?

J'ai défini quatre fonctions qui correspondent à chaque terme à diverses valeurs dudit fichier CSV. Ainsi, chaque terme d'entrée donnera quatre listes de résultats.

Je voudrais stocker les termes d'entrée comme une clé dans un dictionnaire (assez facile) et les quatre listes résultantes en tant que valeurs (également assez facile).

Cependant, parce que la liste d'entrée est de longueur variable, je voudrais mettre en place une fonction pour définir et nommer les dictionnaires de la terme1 ', « TERM2 », illustré très essentiellement ainsi:

term1 = { 'eggs' : [[list1] , [list2] , [list3] , [list4]] } 
term2 = { 'ham' : [[list1] , [list2] , [list3] , [list4]] } 
term3 = { 'bacon' : [[list1] , [list2] , [list3] , [list4]] } 

est-il a) un moyen de nommer des dictionnaires comme celui-ci? et b) ET les ont-ils globalement disponibles? Si c'est le cas, comment? Toute aide est très appréciée.

+7

Pourquoi ne pas définir un dictionnaire avec toutes les données qu'il contient? Il sera beaucoup plus facile de le manipuler et d'accéder à ses valeurs – eumiro

+0

Votre exemple n'est pas valide Python. Vous avez une clé avec plusieurs valeurs, ce qui est un 'SyntaxError: syntaxe invalide. ' –

+0

@Joe non ce n'est pas.Est-ce que vous avez manqué les crochets externes sur les valeurs? Ils sont chacun une liste de listes. le code dans un interpréteur (à condition que je définis list1..list4) et Python l'analyse très bien –

Répondre

2

Pas une approche que je recommanderais, mais vous pouvez accéder aux espaces de noms locaux et globaux en tant que dictionnaires; par exemple. vous pouvez ajouter des variables arbitraires à ces namespaces en utilisant l'interface familière dict:

>>> globals()['foo'] = 'bar' 
>>> foo 
'bar' 
>>> locals()['spam'] = 'eggs' 
>>> spam 
'eggs' 

Vous sera INTRODUISE conflits de noms bien. Aussi, comment le reste de votre code va savoir quelles variables globales contiennent vos résultats? Ils devront aussi faire des recherches indirectes!

Vous feriez mieux d'utiliser un dictionnaire contenant vos résultats, et que ce soit l'espace de noms à la place de l'espace de noms global.

+0

Pourquoi un vote de -1? J'ai dit que le PO ne veut vraiment pas le faire s'il peut l'aider –

+1

L'info-bulle Downvote lit "Cette réponse n'est pas utile". Ce n'était pas mon downvote, mais je remettrais en question l'utilité (ou même l'utilité) d'une réponse qui commence par "pas une approche que je recommanderais ..." - pourquoi poster en premier lieu alors? Surtout que la situation du PO n'est pas proche d'un cas limite qui pourrait justifier la méthode que vous décrivez. – PaulMcG

+1

La modification des locaux() est interdite http://docs.python.org/library/functions.html#locals –

3

Vous pouvez essayer quelque chose comme ceci:

results = {} 
for name in ['eggs', 'ham', 'bacon']: 
    results[name] = (function1(name), function2(name), function3(name), function4(name),) 

où Yevol sont vos fonctions qui renvoie le résultat Listx à partir du fichier CSV ou autre.

Ici, vous aurez dans les résultats DICTIONNAIRE quelque chose comme ceci:

results = { 
    'eggs' : (egg_list1, egg_list2, egg_list3, egg_list4), 
    'ham' : (ham_list1, ham_list2, ham_list3, ham_list4), 
    'bacon' : (bacon_list1, bacon_list2, bacon_list3, bacon_list4), 
} 
+0

Si chaque fonction lit le fichier CSV, ce fichier sera traité '(nombre de clés) X (nombre de fonctions)' fois. Parfois cela ne peut pas être aidé, mais il y a souvent une approche orthogonale qui lit le fichier CSV une seule fois, et met à jour les valeurs dans les résultats au fur et à mesure. – PaulMcG

+0

Cela a bien fonctionné. Merci pour l'aide. – Dingo

3

Voici comment vous pouvez pré-initialiser un dictionnaire contenant toutes les données:

a = "eggs bacon ham".split() 
summary = dict((key,([],[],[],[])) for key in a) 

for lineno,line in enumerate(csv_file): 
    # first element in the line is assumed to be the key ("eggs", "bacon", etc.) 
    key = line[0] 
    # update the data values for this key 
    summary[key][0].append(lineno) 
    summary[key][1].append(something_else) 
    # ... etc. 

Je trouve ce genre de l'accès indexé est un peu fragile, et préfère l'accès par clé ou par attribut. Votre liste codée en dur de 4 listes peut être mieux représentée comme dict ou même comme objet d'une simple classe de pointage de données. De plus, je pense que votre liste "oeufs", "bacon" et "jambon" augmentera au fil du temps, comme vous trouvez des entrées dans votre fichier CSV pour "crêpes", "gaufres", "hash browns" et ainsi sur. J'ai eu à utiliser de plus en plus ces derniers temps defaultdict pour le comptage de données lorsque je passe par des fichiers de données ou des tables de bases de données. Au lieu de pré-définir quelles touches je vous attendre à obtenir (et d'avoir à mettre à jour la liste moi-même lorsque les données d'entrée obtient de nouvelles valeurs ajoutées à elle), defaultdict ajoute que de nouvelles entrées de la forme que je définis:

class Tally(object): 
    def __init__(self): 
     self.count = 0 
     self.lines = [] 
     self.values = [] 

from collections import defaultdict 
summary = defaultdict(Tally) 

for lineno,line in enumerate(csv_file): 
    # first element in the line is assumed to be the key ("eggs", "bacon", etc.) 
    key = line[0] 
    # update the data values for this key 
    summary[key].count += 1 
    summary[key].lines.append(lineno) 
    summary[key].values.append(line[1]) 
    # ... etc. 

defaultdict me sauve le lourd et répétitif "si la clé n'est pas dans le résumé: ajouter une nouvelle entrée ..."overhead, donc mon code reste assez propre

+0

C'est un peu avancé pour moi à ce stade, mais j'ai réussi à adapter votre technique et à la faire fonctionner. Merci pour l'aide. – Dingo