views:

65

answers:

3

Forgive me if this has been asked before. I did not know how to search for it.

I'm quite familiar with the following idiom:

def foo():
    return [1,2,3]

[a,b,c] = foo()
(d,e,f) = foo()

wherein the values contained within the left hand side will be assigned based upon the values returned from the function on the right.

I also know you can do

def bar():
    return {'a':1,'b':2,'c':3}

(one, two, three) = bar()
[four, five, six] = bar()

wherein the keys returned from the right hand side will be assigned to the containers on the left hand side.

However, I'm curious, is there a way to do the following in Python 2.6 or earlier:

{letterA:one, letterB:two, letterC:three} = bar()

and have it work in the same manner that it works for sequences to sequences? If not, why? Naively attempting to do this as I've written it will fail.

A: 

No, if you can not change bar function, you could create a dict from the output pretty easily.

This is the most compact solution. But I would prefer to modify the bar function to return a dict.

dict(zip(['one', 'two', 'three'], bar()))
mikerobi
Why was this downvoted?
mikerobi
@mikerobi - I think they downvoted you because your solution only captures the keys of the dictionary returned by the bar function but assigns them to the values of the produced dictionary. I did not downvote you, however, so I'm just conjecturing.
wheaties
+1  A: 

Dictionary items do not have an order, so while this works:

>>> def bar():
...     return dict(a=1,b=2,c=3)
>>> bar()
{'a': 1, 'c': 3, 'b': 2}
>>> (lettera,one),(letterb,two),(letterc,three) = bar().items()
>>> lettera,one,letterb,two,letterc,three
('a', 1, 'c', 3, 'b', 2)

You can see that you can't necessarily predict how the variables will be assigned. You could use collections.OrderedDict in Python 3 to control this.

Mark Tolonen
+1 and i want to emphasize the "you can't necessarily predict how the variables will be assigned" part!
THC4k
+1  A: 

If you modify bar() to return a dict (as suggested by @mikerobi), you might want to still preserve keyed items that are in your existing dict. In this case, use update:

mydict = {}
mydict['existing_key'] = 100

def bar_that_says_dict():
    return { 'new_key': 101 }

mydict.update(bar_that_says_dict())

print mydict

This should output a dict with both existing_key and new_key. If mydict had a key of new_key, then the update would overwrite it with the value returned from bar_that_says_dict.

Paul McGuire