TheChetan TheChetan - 8 days ago 4
Python Question

Inconsistency using map in python

I have a constants file

constants.py
like so:

querystring = {
"limit":"10000",
"sort":"desc"
}

dummy1 = {
"a": "22",
"q": "*",
}

dummy2 = {
"a": "24",
"q": "**",
}

streams = [dummy1, dummy2]


I'm trying to initialise a list by manipulating the values from the
constants.py
file.

from constants import querystring, streams
def setParams(dummy, querystring):
ld = {}
ld["query"] = setQuerystring( dummy, querystring)
print ld
return ld

def setQuerystring( dummy, querystring):
query = querystring
query["filter"] = "stream:" + dummy["a"]
query["query"] = dummy["q"]
return query

l = map(lambda x: setParams(x, querystring), streams)
print l[0]
print l[1]


While the lambda function is running, the output is correctly printed, but when I see the final value returned by the map, the values are different. Why this inconsistency?

The program output:

{'query': {'sort': 'desc', 'filter': 'stream:22', 'limit': '10000', 'query': '*'}} # l[0] -> during lambda execution
{'query': {'sort': 'desc', 'filter': 'stream:24', 'limit': '10000', 'query': '**'}} # l[1] -> during lambda execution
{'query': {'sort': 'desc', 'filter': 'stream:24', 'limit': '10000', 'query': '**'}} # l[0] -> from map
{'query': {'sort': 'desc', 'filter': 'stream:24', 'limit': '10000', 'query': '**'}} # l[1] -> from map

Answer

You're reusing and modifying the querystring dict across iterations. Later changes from successive iterations are therefore propagated to previously attached copies. You should consider attaching a copy to each dict instead, and modifying that copy:

def setQuerystring( dummy, querystring):
    query = querystring.copy()
    ...

{'query': {'sort': 'desc', 'filter': 'stream:22', 'limit': '10000', 'query': '*'}}
{'query': {'sort': 'desc', 'filter': 'stream:24', 'limit': '10000', 'query': '**'}}
{'query': {'sort': 'desc', 'filter': 'stream:22', 'limit': '10000', 'query': '*'}}
{'query': {'sort': 'desc', 'filter': 'stream:24', 'limit': '10000', 'query': '**'}}