Rob Bednark
Rob Bednark

Reputation: 28152

How to get a tuple of arbitrary values from a dict?

How can I get a tuple of arbitrary values from an anonymous dictionary?

def func():
    return dict(one=1, two=2, three=3)

# How can the following 2 lines be rewritten as a single line,
# eliminating the dict_ variable?
dict_ = func()
(one, three) = (dict_['one'], dict_['three'])

Upvotes: 0

Views: 127

Answers (3)

mgilson
mgilson

Reputation: 309919

An intermediate variable is probably preferable (more readable) than this one-liner:

>>> (one,three) = (lambda d:(d['one'],d['three']))(func())

(which really does nothing other than move the intermediate value into a function which is generated on the fly)

Upvotes: 2

ch3ka
ch3ka

Reputation: 12158

Don't do that, an intermediate dict is fine in most cases. readability counts. If you really find yourself far too often in this situation, you could use a decorator to monkeypatch your function:

In     : from functools import wraps

In     : def dictgetter(func, *keys):
  .....:     @wraps(func)
  .....:     def wrapper(*args, **kwargs):
  .....:         tmp = func(*args, **kwargs)
  .....:         return [tmp[key] for key in keys]
  .....:     return wrapper

In     : def func():
   ....:         return dict(one=1, two=2, three=3)
   ....: 

In     : func2 = dictgetter(func, 'one', 'three')

In     : one, three = func2()

In     : one
Out    : 1

In     : three
Out    : 3

or something like that.

Of course, you could also monkeypatch so that you specify your desired fields on calltime, but then you'd want an ordinary function which wraps these mechanics, I guess.

This would be implemented very similar to the body of def wrapper above, and used like

one, three = getfromdict(func(), 'one', 'three' )

or something like that, but you could also re-use the whole decorator above:

In     : two, three = dictgetter(func, 'two', 'three')()

In     : two, three
Out    : (2, 3)

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1121834

Loop over the func() result?

one, three = [v for k, v in sorted(func().iteritems()) if k in {'one', 'three'}]

Replace .iteritems() with .items() if you are using Python 3.

Demo:

>>> def func():
...     return dict(one=1, two=2, three=3)
... 
>>> one, three = [v for k,v in sorted(func().iteritems()) if k in {'one', 'three'}]
>>> one, three
(1, 3)

Note that this approach requires you to keep your target list in sorted key order, rather a strange limitation for something that should be straightforward and simple.

This is far more verbose than your version. There is nothing wrong with it, really.

Upvotes: 1

Related Questions