Shmink Shmink - 2 months ago 10
Python Question

A variable that's a copy of another is also changing the original

This is a weird one. Unless I'm doing something dumb. I have the following code:

gps_markers = [ ['Example text', 34.4563,-118.1241], [34.5235,-118.1245], [34.6432,-118.1554] ]
new_gps = gps_markers

def make_points(coords):
if(coords):
# Firstly we don't want the hover text.
for x in range(0, len(coords)):
if(len(coords[x]) == 3):
coords[x].pop(0)

new_list = [{'lat': d[0], 'lng': d[1]} for d in coords]
# Return the new list after the list comprehension.
return new_list

print '\nbefore newgps ->', gps_markers

new_gps = make_points(new_gps)

print '\nafter newgps ->', gps_markers


Then running the script I get the following outputs from the print lines.

before newgps -> [['Example text', 34.4563, -118.1241], [34.5235, -118.1245], [34.6432, -118.1554]]

after newgps -> [[34.4563, -118.1241], [34.5235, -118.1245], [34.6432, -118.1554]]


Now for why it doesn't make sense to me. The first variable
gps_markers
shouldn't have been effected at any point in this script, right? I make a copy of
gps_markers
called
new_gps
. I then run
new_gps
through my
make_points
method. Which will effect that said variable. But it also effects
gps_markers
? Not sure if I've just been staring at this for too long or if there is something I'm missing. Feel like a bit of both.

Answer

Python assigns by reference, i.e. new_gps and gps_markers are effectively the same object.

If you need to maintain original list, then you need to make a new list and copy all sublists:

new_gps = [sublist[:] for sublist in gps_markers]

That doesn't apply for all cases (you may have a deeply nested structure), so standard library actually has copy.deepcopy function for that:

import copy
new_gps = copy.deepcopy(gps_markers)