cpps
cpps

Reputation: 43

operator.setitem problem in python 3

I have a problem when using operator.setitem in python 3.

When I use the code below and run it in python 3.1.

people=(('fred','sam','jane','betty'),(1,2,3,4))
p_dict = {}
map(operator.setitem, [p_dict]*len(people[0]), people[0],people[1])
print (p_dict)

>>> {}

That just prints out a empty dictionary {}.

But I use the same code to run in python 2.6. It prints out {'jane': 3, 'betty': 4, 'sam': 2, 'fred': 1} . This is the result I want.

So, can anyone tell me what's the problem when I run this code in python 3? Thanks in advance.

Upvotes: 1

Views: 1073

Answers (3)

Martin v. Löwis
Martin v. Löwis

Reputation: 127527

The problem is that the map() is never 'executed'. In Python 3, map just returns an iterator - the individual elements are only computed when they are needed. To work around that, you might write

list(map(operator.setitem, [p_dict]*len(people[0]), people[0],people[1]))

However, I agree with everybody else that you shouldn't be using map in the first place - as you don't really need to result of the map application.

Upvotes: 2

AndiDog
AndiDog

Reputation: 70208

In Python 3, the result of map is lazy which can give you headache when debugging stuff that worked flawlessly in older versions of Python. In other words, it is a generator, so you have to consume it in order to set the items in your dictionary.

You should rather do this with a for loop in this case:

people=(('fred','sam','jane','betty'),(1,2,3,4))
p_dict = {}
for key, value in zip(*people):
    p_dict[key] = value
# Now p_dict is {'jane': 3, 'betty': 4, 'sam': 2, 'fred': 1}

or with a simple dict constructor: dict(zip(*people)).

Upvotes: 1

orlp
orlp

Reputation: 117771

That's a very unpythonesque way to do it. This is much better (and more efficient):

people = (('fred','sam','jane','betty'), (1,2,3,4))
p_dict = dict(zip(*people))

Works on 2.x and 3.x.

Upvotes: 3

Related Questions