0

I have never come across this before and wonder if anyone has a solution. I have a while loop with a function inside that returns an integer. The function takes a string and a list. The first iteration of the while loop returns the correct answer but on subsequent iterations the list seems to be empty even though the function does not change the list in any way. Also if i try to reset the list after the function in the while loop the new list also seems to be empty. It seems to be very strange behavior. Any explanation as to whats going on would be much appreciated. The code of the function inside the loop is quite long so at this stage I will avoid posting it. However if requested then I will post.

 spectrum = [1,2,3,4,5,6]
 leaderboard = ['zzz','xxx','yyy']
 pep_scores = []
 j=0
 original_spectrum = spectrum
 print len(original_spectrum)
 while j < len(leaderboard):
      x= linear_score(leaderboard[j],spectrum)  #this function doesn't alter spectrum
      print leaderboard[j], x
      spectrum = original_spectrum     #should reset spectrum even though it shouldn't be necessary to do that
      print len(spectrum), len(original_spectrum) #prints 2 empty lists
      pep_scores.append(x) #appends correct score on 1st iteration and '0' for all others
      j=j+1

I had added print statements to try to resolve the problem, my original code did not contain 'original_spectrum = spectrum' or 'spectrum = original_spectrum' in the while loop. I don't understand why after 1 iteration 'origninal_spectrum' is an empty list. I haven't posted the function because I cannot see how it could be causing the problem. Please ask if you need more information.

user3062260
  • 1,584
  • 4
  • 25
  • 53
  • 2
    `original_spectrum = spectrum` **does not** create a copy. Are you certain `linear_score` doesn't mutate its arguments? Without a complete [minimal example](http://stackoverflow.com/help/mcve), it's very hard to help. – jonrsharpe Nov 13 '14 at 11:33
  • thanks, when I print original_spectrum to the screen before the loop it is exactly the same as spectrum? How would I create a copy if not this way. I am 100% certain that the function doesn't alter its arguments. SOrry for the minimal posting but the function is quite long and contains several other also quite long nested functions – user3062260 Nov 13 '14 at 11:42
  • See http://stackoverflow.com/q/2612802/3001761. If your code is long, you should cut it down to the smallest part that causes the problem - this will help you find the bug without having to ask. – jonrsharpe Nov 13 '14 at 11:44
  • possible duplicate of [Python references](http://stackoverflow.com/questions/2797114/python-references) – simonzack Nov 13 '14 at 12:04

2 Answers2

3

To create copy of the list use copy_list = original_list[:].

So in your example:

spectrum = [1,2,3,4,5,6]
leaderboard = ['zzz','xxx','yyy']
pep_scores = []
j=0
original_spectrum = spectrum[:]
print len(original_spectrum)
while j < len(leaderboard):
    x= linear_score(leaderboard[j],spectrum)  #this function doesn't alter spectrum
    print leaderboard[j], x
    spectrum = original_spectrum[:]     #should reset spectrum even though it shouldn't be necessary to do that
    print len(spectrum), len(original_spectrum) #prints 2 empty lists
    pep_scores.append(x) #appends correct score on 1st iteration and '0' for all others
    j=j+1
utek
  • 821
  • 1
  • 7
  • 9
2

Its because of that you define spectrum outside the function and its scope is global , and when you pass spectrum to your function as its the name of list any changes on it change it globally not local in your function ! and note that its just about mutable (like lists) objects . (Note : labels are pointer to special memory addresses ) (your copy command original_spectrum = spectrum just make 2 label for one object !!! )

for better understanding see the below example :

>>> a=[1,2,3]
>>> def f(s):
...  s.remove(1)
... 
>>> f(a)
>>> a
[2, 3]

>>> def f(s):
...  s+=[1,2]
... 
>>> f(a)
>>> a
[2, 3, 1, 2]

Now you have 2 choice :

  1. make a copy of spectrum and pass that to function :

copy_spectrum = spectrum[:]

  1. define spectrum inside the function and one outside for global usage !
Mazdak
  • 105,000
  • 18
  • 159
  • 188