lprsd
lprsd

Reputation: 87077

Python dictionary simple way to add a new key value pair

Say you have,

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

And you want

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

I know you can do,

d['foo'] = foo

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

But, in all these way to add the variable foo to dict, I have had to use the word foo twice; once to indicate the key and once for its value.

It seems wasteful to me to use foo twice. Is there a simpler way, in which you can tell python "Add this variable to the dictionary with its name as the key and its value as the value"?

Upvotes: 1

Views: 18288

Answers (7)

derks
derks

Reputation: 556

It seems to me what you are talking about is an enhancement to parameter passing functionality:

def func(*vars):

provides a tuple of ordered values without keys

def func(**vars):

provides a dict of key value pairs, that MUST be passed as key=value pairs.

def func(***vars):

WOULD PROVIDE a dict of key value pairs, passed either explicitly as key=value, or implicitly as key (a variable, literals would cause error without key=)

SO:

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

But of course, this is just wishful thinking...

Upvotes: 0

nikow
nikow

Reputation: 21548

To add all the local variables to a dict you can do:

d.update(locals())

The same works for function calls:

func(**locals())

Note that depending on where you are locals() might of course contain stuff that should not end up in the dict. So you could implement a filter function:

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

filtered_update(d, locals())

Of course the Python philosophy is "explicit is better than implicit", so generally I would walk the extra mile and do this kind of stuff by hand (otherwise you have to be careful about what goes on in your local namespace).

Upvotes: 1

Wim
Wim

Reputation: 11242

If you don't want to pass all of locals() (which may be a security risk if you don't fully trust the function you're sending the data too), a one-line answer could be this:

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

or in Python 3.0 this would become possible:

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

Upvotes: 1

R Hyde
R Hyde

Reputation: 10409

You could use eval, although I'm not sure that I'd recommend it.

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


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

Edit: I should point out why I don't recommend "eval". What happens if you do something like this? (from: 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

Upvotes: 0

Nick Craig-Wood
Nick Craig-Wood

Reputation: 54081

Actutally using foo twice is remarkably common in python programs. It is used extensively for passing on arguments eg

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

Which is a specialised case of the dictionary manipulations in your question.

I don't think there is a way of avoiding it without resorting to magic, so I think you'll have to live with it.

Upvotes: 2

Anurag Uniyal
Anurag Uniyal

Reputation: 88717

you can do something like this

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

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

Upvotes: 4

Ned Batchelder
Ned Batchelder

Reputation: 375474

You can use:

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

I don't see the difference between your d and e cases: both set 'foo' to the value of foo.

It gets trickier if you want to bury this in a function:

def add_variable(d, name):
    # blah

because then it has to use inspect to start poking around in frames.

This sounds like a larger problem that might have a nicer solution if you wanted to describe it to us. For example, if the problem is that you don't care just about foo, but in fact, a whole slew of local variables, then maybe you want something like:

d.update(locals())

which will copy the names and value of all the local variables into d.

Upvotes: 2

Related Questions