Reputation: 21261
I have this code.
List1 = [{'pg_id': 100, "group_name": "test1", "product_price": 100}, {'pg_id': 200, "group_name": "test2", "product_price": 200}]
List2 = [{'lowest_price': 20}]
FINAL_DICT = {}
for latest_lowest in List1:
for idx, coupon_related__product in enumerate(List2):
if coupon_related__product['lowest_price'] < latest_lowest['product_price']:
FINAL_DICT[ latest_lowest['pg_id'] ] = coupon_related__product
FINAL_DICT[ latest_lowest['pg_id'] ]['group_name'] = latest_lowest['group_name']
print("Group name is %s"%(latest_lowest['group_name']))
for PG_ID, LOWEST_PRICED_PRODUCT_THIS_PG in FINAL_DICT.iteritems():
print(LOWEST_PRICED_PRODUCT_THIS_PG)
My desired output in terminal is
Group name is test1
Group name is test2
{'lowest_price': 20, 'group_name': 'test2'}
{'lowest_price': 20, 'group_name': 'test1'}
But it outputs
Group name is test1
Group name is test2
{'lowest_price': 20, 'group_name': 'test2'}
{'lowest_price': 20, 'group_name': 'test2'}
If I change
FINAL_DICT[ latest_lowest['pg_id'] ] = coupon_related__product
to
FINAL_DICT[ latest_lowest['pg_id'] ] = coupon_related__product.copy()
Then it produces correct output which I want.
My question is, why all of the dictionaries in FINAL_DICT
has group_name=test2
when I don't use .copy()
Upvotes: 0
Views: 58
Reputation: 140186
this line:
FINAL_DICT[ latest_lowest['pg_id'] ] = coupon_related__product
assigns a dictionary to your entry. The next line:
FINAL_DICT[ latest_lowest['pg_id'] ]['group_name'] = latest_lowest['group_name']
changes the group name, but the reference of the dict is the last dictionary you assigned to, so the reference is shared.
that's why you have to make an copy of the dict so references are independent:
FINAL_DICT[ latest_lowest['pg_id'] ] = coupon_related__product.copy()
now modifying FINAL_DICT[ latest_lowest['pg_id'] ]['group_name']
doesn't change the values of others FINAL_DICT[ latest_lowest['pg_id'] ]
Upvotes: 2
Reputation: 4634
In Python dictionaries are mutable objects and are therefore not copied by default. You can read more about this here: python dictionary passed as an input to a function acts like a global in that function rather than a local
If the whole pass by name vs pass by value vs pass by reference thing is too confusing then all you need to know is that Python does not normally make a copy of a list
or dict
when assigning values using =
. When you want to make a copy of a list
or dict
you need to explicitly tell Python you would like a copy. So in summary
x = {"hello": "world"}
y = x
y["hello"] = "not world"
print("x is " + str(x))
print("y is " + str(y))
> x is {'hello': 'not world'}
> y is {'hello': 'not world'}
vs
x = {"hello": "world"}
y = x.copy()
y["hello"] = "not world"
print("x is " + str(x))
print("y is " + str(y))
> x is {'hello': 'world'}
> y is {'hello': 'not world'}
Upvotes: 1