Malcolm
Malcolm

Reputation: 752

python element of class copied accros new instances

I have class named KSlamComp that read numbers from a file and put it in two attributes gt_raw and slam_raw

class KSlamComp:
    def __init__(self, forward_nodes_lookup = 1, backward_nodes_lookup = 0, slam_input_raw = data.Data(), gt_input_raw = data.Data()):
        self.slam_raw = slam_input_raw
        self.gt_raw = gt_input_raw
        self.nb_node_forward = forward_nodes_lookup
        self.nb_node_backward = backward_nodes_lookup

    def read(self, file_name):
        assert(len(self.slam_raw.posetime) == 0)
        f = open(file_name, 'r')
        for line in f:
            print("line")
            assert len(line.split()) == 8

            slampose = data.Pose(data.Point( float(line.split()[0]), float(line.split()[1] )),  float(line.split()[2]))
            gtpose = data.Pose(data.Point( float(line.split()[4]), float(line.split()[5] )),  float(line.split()[6]))

            self.slam_raw.posetime.append( (slampose, float(line.split()[3]) ) )
            self.gt_raw.posetime.append( (gtpose, float(line.split()[7]) ) )


    def printraw(self):
        print("Printing Raw data")
        for x in range(0, len(self.slam_raw.posetime)):
            print(str(self.slam_raw.posetime[x][0].getPosition().x) + " " \
                + str(self.slam_raw.posetime[x][0].getPosition().y) + " " \
                + str(self.slam_raw.posetime[x][0].getOrientation()) + " " \
                + str(self.slam_raw.posetime[x][1]) + " " + \
                  str(self.gt_raw.posetime[x][0].getPosition().x) + " " \
                + str(self.gt_raw.posetime[x][0].getPosition().y) + " " \
                + str(self.gt_raw.posetime[x][0].getOrientation()) + " " \
                + str(self.gt_raw.posetime[x][1]))
        print("\n")

The Data is simply something along those lines

class Data:
    def __init__(self):
        #Tuple with pose and time 
        self.posetime = list()

Now I have this test file

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from kslamcomp import data
from kslamcomp import kslamcomp

def main():
    # parse command line options
    d = kslamcomp.KSlamComp(1, 0)
    d.read("data_files/shifted.txt")
    d.printraw()
    d.print()

    d_invert = kslamcomp.KSlamComp()
    d_invert.printraw()
    d.printraw()

if __name__ == "__main__":
    main()

My understanding was that d_invert is a new object KSlamComp with all attribute initialised to their default value. Especially, self.slam_raw and self.gt_raw are empty Data objects with empty lists. Hoever when I run this program, I have

$ python3 test_sanity.py 
line
line
line
line
Printing Raw data
1.0 1.0 1.0 2.0 3.0 3.0 3.0 6.0
5.0 5.0 5.0 6.0 8.0 8.0 7.1 14.0
9.0 9.0 9.0 10.0 11.0 11.0 11.0 2.0
13.0 13.0 13.0 14.0 15.0 15.0 15.0 10.0


Printing Raw data
1.0 1.0 1.0 2.0 3.0 3.0 3.0 6.0
5.0 5.0 5.0 6.0 8.0 8.0 7.1 14.0
9.0 9.0 9.0 10.0 11.0 11.0 11.0 2.0
13.0 13.0 13.0 14.0 15.0 15.0 15.0 10.0


Printing Raw data
1.0 1.0 1.0 2.0 3.0 3.0 3.0 6.0
5.0 5.0 5.0 6.0 8.0 8.0 7.1 14.0
9.0 9.0 9.0 10.0 11.0 11.0 11.0 2.0
13.0 13.0 13.0 14.0 15.0 15.0 15.0 10.0

While I thought the second print whould have been empty it seems to contain the data that was read in the first KSlamComp object.

Why are slef.gt_raw and Self.slam_raw the same object in both object ? If I initialised them "manually" by calling d_invert = kslamcomp.KSlamComp(0, 1, data.Data(), data.Data()) it seems to work but I thought that having the default parameter was the same.

Upvotes: 0

Views: 38

Answers (1)

hello world
hello world

Reputation: 624

You should not use mutable objects as a defaults of function, because defaults are stored inside a function object. I would probably write

class KSlamComp:
    def __init__(..., slam_input_raw = None, gt_input_raw = None, ...) 
        self.slam_raw = slam_input_raw or data.Data()
        self.gt_stuff = gt_input_raw or data.Data()

Upvotes: 2

Related Questions