Bram Adams
Bram Adams

Reputation: 73

Variable getting new value in same loop iteration

I'm running into an issue where basically a variable I set at the top of the loop is getting a new value before the end of the iteration. How do I change this so it doesn't happen? I think it has something to do with scope, but I'm not entirely sure. Relevant code and output below:

while not stop(old_centers, centers): #returns True when old centers == new ones
    
    old_centers = centers #setting old centers to centers, nothing fancy
    print 'old_centers', old_centers

    centers = label(points, centers)#calls the label func and assigns centers a new value

    print 'old centers ', old_centers, '\n new ones ', centers

    print '# of iterations: %d' % iterations
    iterations += 1

And here is the output:

initial centers {'1': [1.193013180404786, 1.3490890491331484], '0': [0.10173245995124558, 0.2259745323785607], '2': [1.1969102753605907, 1.1584028826056012]}

old_centers {'1': [1.193013180404786, 1.3490890491331484], '0': [0.10173245995124558, 0.2259745323785607], '2': [1.1969102753605907, 1.1584028826056012]}

new centers in label {'1': [1.1646709311677974, 1.7595898757959954], '0': [0.23028481023828123, 0.9213541910575308], '2': [1.3055269036979071, 0.6867418777771471]}

old centers {'1': [1.1646709311677974, 1.7595898757959954], '0': [0.23028481023828123, 0.9213541910575308], '2': [1.3055269036979071, 0.6867418777771471]}

new ones {'1': [1.1646709311677974, 1.7595898757959954], '0': [0.23028481023828123, 0.9213541910575308], '2': [1.3055269036979071, 0.6867418777771471]}

# of iterations: 0

As you can see, my old_centers variable is changed by the end of the loop, forcing the while loop to cancel after the first iteration. At first, it correctly receives the initial dict, but after label is called, it changes and I have no idea why. Any tips on why this is happening?

Upvotes: 0

Views: 88

Answers (1)

Padraic Cunningham
Padraic Cunningham

Reputation: 180411

You need to copy.deepcopy,just using copy will not work as you have lists as values so any changes in any list will also change in old_centers:

from copy import deepcopy

old_centers = deepcopy(centers)

old_centers = centers creates a reference to centers so any changes to centers are reflected in old_centers as both objects are pointing to the same location in memory, both are in fact the same object. c is d:

d = {1:2}
c = d
d[1] = 4
print(id(c),id(d))
print(c,d)
print(c is d)

140661961276040 140661961276040 # same id same objects
{1: 4} {1: 4}
True

Now copy:

from copy import deepcopy
d = {1: 2}
c = deepcopy(d) # create new object
d[1]= 4
print(id(c),id(d))
print(c,d)
print(c is d) 

140477200628872 140477200628360 # now two different id's two different objects
{1: 2} {1: 4}
False 

Upvotes: 1

Related Questions