2009-11-12 4 views
1

Supposons que vous avez,Python dictionnaire moyen simple d'ajouter une nouvelle valeur paire de clés

foo = 'bar' 
d = {'a-key':'a-value'} 

Et vous voulez

d = {'a-key':'a-value','foo':'bar'} 
e = {'foo':foo} 

Je sais que vous pouvez faire,

d['foo'] = foo 

#Either of the following for e 
e = {'foo':foo} 
e = dict(foo=foo) 

Mais, de toutes ces façons d'ajouter la variable foo à dict, j'ai dû utiliser le mot foo deux fois; une fois pour indiquer la clé et une fois pour sa valeur. Il me semble inutile d'utiliser foo deux fois. Existe-t-il un moyen plus simple, dans lequel vous pouvez dire à python "Ajouter cette variable au dictionnaire avec son nom comme clé et sa valeur comme valeur"?

+0

comment arrivez-vous à votre 'foo = 'bar''. Y a-t-il un moyen d'ignorer cet état? ou pour avoir 'dict':' {'foo': 'bar'} 'à la place? – SilentGhost

Répondre

2

Actutally utilisant foo est deux fois remarquablement commun dans les programmes de python. Il est largement utilisé pour transmettre des arguments, par exemple

def f(foo, bar): 
    g(foo=foo) 

Ce qui est un cas spécialisé des manipulations de dictionnaire dans votre question.

Je ne pense pas qu'il existe un moyen de l'éviter sans avoir recours à magic, donc je pense que vous devrez vivre avec.

+0

Oui. il est certainement commun, et je pense à éviter, à chaque fois. Ma question, en général couvre cette répétition générale aussi. –

2

Vous pouvez utiliser:

name = 'foo' 
d[name] = vars[name] 

je ne vois pas la différence entre vos d et e cas: les deux ensemble « foo » à la valeur de foo.

Il est plus compliqué si vous voulez enterrer cela dans une fonction:

def add_variable(d, name): 
    # blah 

car alors il doit utiliser inspect pour commencer à fouiner dans des cadres.

Cela ressemble à un plus gros problème qui pourrait avoir une meilleure solution si vous vouliez nous le décrire. Par exemple, si le problème est que vous ne vous souciez pas seulement foo, mais en fait, toute une série de variables locales, alors peut-être que vous voulez quelque chose comme:

d.update(locals()) 

qui copie les noms et la valeur des toutes les variables locales dans d.

+0

Ned: Ceci est un modèle de django commun, le retour render_to_resp ('modèle', { 'a': a, 'b ": b, 'c': c}). Wont mieux si je pouvais le faire, render_to_resp (' modèle », func (a, b, c, d)) – agiliq

+0

Exactement: Qu'en est-il:' render_to_response? ('modèle', locals()) ' –

+0

Works, mais pour permettre un accès de modèle peut-être dangereux pour * tous * de votre région variables peuvent ne pas être souhaitable. – Wim

4

vous pouvez faire quelque chose comme ça

def add_dry_foo(d, namespace, fooName): 
    d[fooName] = namespace[fooName] 

foo = 'oh-foo' 
d = {} 
add_dry_foo(d, locals(), 'foo') 
print d 
0

Vous pouvez utiliser eval, bien que je ne suis pas sûr que je le recommande.

>>> d = dict() 
>>> foo = 'wibble' 
>>> def add(d, name): 
     d[name] = eval(name) 


>>> add(d, 'foo') 
>>> d 
{'foo': 'wibble'} 

Edit: Je dois préciser pourquoi je ne recommande pas "eval". Que se passe-t-il si vous faites quelque chose comme ça? (À partir de: http://mail.python.org/pipermail/tutor/2005-November/042854.html)

>>> s = "(lambda loop: loop(loop)) (lambda self: self(self))" 
>>> add(d, s) 

Traceback (most recent call last): 
    File "<pyshell#54>", line 1, in <module> 
    add(d, s) 
    File "<pyshell#43>", line 2, in add 
    d[name] = eval(name) 
    File "<string>", line 1, in <module> 
    File "<string>", line 1, in <lambda> 
    File "<string>", line 1, in <lambda> 
    ... 
    File "<string>", line 1, in <lambda> 
RuntimeError: maximum recursion depth exceeded 
1

Pour ajouter toutes les variables locales à un dict que vous pouvez faire:

d.update(locals()) 

Les mêmes œuvres pour des appels de fonction:

func(**locals()) 

Notez que selon l'endroit où vous êtes locals() pourrait évidemment contenir des choses qui ne devraient pas finir dans le dict. Ainsi, vous pouvez mettre en œuvre une fonction de filtre:

def filtered_update(d, namespace): 
    for key, value in namespace.items(): 
     if not key.startswith('__'): 
      d[key] = value 

filtered_update(d, locals()) 

Bien sûr, la philosophie Python est « explicite est mieux que implicite », de façon générale, je marche le mile supplémentaire et faire ce genre de choses à la main (sinon vous devez faites attention à ce qui se passe dans votre espace de noms local).

1

Si vous ne voulez pas passer tous locals() (qui peut être un risque pour la sécurité si vous ne pas entièrement confiance à la fonction que vous envoyez les données aussi), une réponse d'une ligne pourrait être celle-ci:

dict([ (var, locals()[var]) for var in ['foo', 'bar'] ])

ou en Python 3.0, deviendrait possible:

{ var: locals()[var] for var in ['foo', 'bar'] }

+0

+1 pour la compréhension dict de Py3K –

0

Il me semble que vous parlez est une amélioration à p fonctionnalité de passage de arameter:

def func(*vars): 

fournit un tuple de valeurs ordonnées sans touches

def func(**vars): 

fournit un dict de paires de valeurs clés, qui doit être passé en clé = valeur paires.

def func(***vars): 

fournirait une dict de paires de valeurs clés, passé soit explicitement comme clé = valeur, ou implicitement comme clé (une variable, littéraux causerait erreur sans key =)

SO:

(x1,x2,x3) = (1,2,3) 
def myfunc(***vars): 
    retrun vars 
myfunc(x1,x2,x3) 
>>> {'x1':1,'x2':2,'x3':3} 

Mais bien sûr, thi s est juste un vœu pieux ...

Questions connexes