0

I have a python-script which should read values from a txt-file, process a backup of them, and then plot them. The code is as following:

class fit_to_init_values:
    def __init__(self, filename):
        lines = tuple(open(filename, 'r'))
        self.arr = []
        self.xdata = []
        self.xdata_old = []
        self.ydata = []
        self.ydata_old = []
        print len(lines)
        for elem in lines:
            a = elem.split(", ")
            if len(a) == 3:
                data = data_point(float(a[0]), float(a[1]))
                self.arr.append(data)
            else:
                print len(a)
        for elem in self.arr:
            self.xdata.append(elem.x)
            self.ydata.append(elem.y)
        self.xdata_old = self.xdata
        print self.xdata[0]
        self.ydata_old = self.ydata    

    def reduce_stuff(self):
        idx = self.ydata.index(max(self.ydata))
        self.max1 = max(self.xdata)
        tmp = self.xdata
        for i, elem in enumerate(tmp):
            tmp[i] = (tmp[i] - 1.254111749e14)/self.max1
        print self.xdata[0]

    def plot_data(self, num):
                if num == 0:
                    plt.plot(self.xdata_old, self.ydata_old, 'bs')
                    print("Plot 0")
                    plt.show()

and it is called as:

test = fit_to_init_values("pulse1.txt")
test.reduce_stuff()
test.plot_data(0)

Now the output of this is:

4096
7.42611749e+13
-0.289578281623
Plot 0

what means that apparently self.xdata got modified by the reduce_stuff()-function. The same happens if I replace print self.xdata[0] with print self.xdata_old[0]. Why do these values change, even if I am never operating on them?
If necessary, I can also provide the file "pulse1.txt".

arc_lupus
  • 3,942
  • 5
  • 45
  • 81

1 Answers1

1

you are only copying reference of the ydata to ydata_old. So when you change ydata, ydata_old gets changed.

try this

import copy
self.ydata_old = copy.deepcopy(self.ydata)
self.xdata_old = copy.deepcopy(self.xdata)

deepcopy copies the whole object to ydata_old not just the reference.

This happens because lists are mutable and any changes you make to new data gets reflected in old data.

To clarify the doubts on the comment, why the same works in

a=5
b=a
a += 2
a==7
b==5

try this

>>> a=5
>>> id(a)
140547708740344
>>> b=a
>>> id(b)
140547708740344
>>> a+=2
>>> id(a)
140547708740296
>>> id(b)
140547708740344

Here 'a' is mutable, b=a assigns reference of a to b Now when a += 2 is called, a new object is created and reference of that is assigned to 'a' leaving 'b' as it is. here you can see that the id of 'a' changes when you do a+=2, hope that helps

for further explanation on mutable vs immutable, try this:- Immutable vs Mutable types

Community
  • 1
  • 1
Namit Singal
  • 1,506
  • 12
  • 26
  • But why is then something like `a=5; b=a; a += 2` with `b == 5; a == 7` working? – arc_lupus Jun 05 '15 at 10:12
  • these are immutable objects, so their values cannot be changed, rather, a +=2 gives a new object and assigns it to a, b still referring to the same object does not change. Lists are mutable, so the values can be changed – Namit Singal Jun 05 '15 at 10:13
  • >>> a=5 >>> id(a) 140547708740344 >>> b=a >>> id(b) 140547708740344 >>> a+=2 >>> id(a) 140547708740296 >>> id(b) 140547708740344 here you can see that the id of a changes when you do a+=2, hope that helps – Namit Singal Jun 05 '15 at 10:16