0

I have a problem concerning copying object attributes, and making sure the attributes are not bound together

I am implementing Data Tables in python, whose attributes are rows : list [ list ] column_names : list[str]

I want to have a method that copy a table, to make modifications for instance, but I want it to be fully independent from the original table in order to have a non destructive approach

    def copy(self):
        print(Fore.YELLOW + "COPY FCN BEGINS" + Fore.WHITE)
        rows = list(self.rows)
        
        # FOR DEBUG PURPOSES
        pprint(rows)
        pprint(self.rows)
        print(f'{rows is self.rows}')
        
        names = list(self.column_names)

        # FOR DEBUG PURPOSES
        pprint(names)
        pprint(self.column_names)
        print(f'{names is self.column_names}')
        print(Fore.YELLOW + "COPY FCN ENDS" + Fore.WHITE)

        return Tableau( rows= rows, column_names= names )

Then I test it creating a table and copying it into another then i modify the new table and make sure it modified the latest only

Problem : it modifies both however i made sure that the rows' list were not pointing to the same object so i am a bit confused

here are the rsults

result of copy function

and here is the test function (using unittest)

the test function :

        def test_copy(self):

        # on s'assure que les deux Tableaux sont bien identiques après la copie, mais différents si on en modifie l'un ( ils ne aprtagent pas la même liste en terme d adresse mémoire )

        # on copie

        NewTable = self.TableauA.copy()
    
        self.assertEqual(NewTable.rows, self.TableauA.rows)
        self.assertEqual(NewTable.column_names, self.TableauA.column_names)


        print("Row B")
        pprint(self.rowB)
        print("New Table")
        print(NewTable)
        print("tableau A")
        print(self.TableauA)

        print( Fore.GREEN + "IS THE SAME OBJECT ?" + Fore.WHITE)
        print(f"{NewTable is self.TableauA}")
        print( Fore.GREEN + "ROWS IS THE SAME OBJECT ?" + Fore.WHITE)
        print(f"{NewTable.rows is self.TableauA.rows}")
        print( Fore.GREEN + "NAMES IS THE SAME OBJECT ?" + Fore.WHITE)
        print(f"{NewTable.column_names is self.TableauA.column_names}")

        # on modifie le nouveau Tableau
        NewTable.add_column(name="NewCol", column=self.rowB)

        print(Fore.YELLOW + "MODIFICATION" + Fore.WHITE)

        print(Fore.GREEN + "New Table" + Fore.WHITE)
        print(NewTable)
        print(Fore.GREEN + "tableau A" + Fore.WHITE)
        print(self.TableauA)
        # on s'assure qu'on a pas modifié les lignes dans les deux
        self.assertNotEqual(NewTable.rows, self.TableauA.rows)

        return

and the results :

results of the test function

and finally : the add_column method

    def add_column(self, name : str, column : list, position : int =-1):
        n =len(self.rows)
        if position == -1 :
            position = n
        for k in range(n) :
            self.rows[k].insert(position, column[k])
        self.column_names.insert(position, name)
        return

Thank you !

  • 4
    There is a lot of irrelevant code here, please consider making a [mre] for your future questions. You should probably have a look at https://stackoverflow.com/questions/17246693/what-is-the-difference-between-shallow-copy-deepcopy-and-normal-assignment-oper – Thierry Lathuille May 18 '21 at 14:21

1 Answers1

1

I found it, in the end it was very subtle as a list of list the highest list in hierarchy : rows was indeed unique however the content of rows [the list that contains lists] was not : the observation lists were still tied even with the list() function

here is how i made them unique

rows = [ list( self.rows[k] ) for k in range( len(self.rows) ) ]

here is the final code that wortks :

    def copy(self):

        rows = [ list( self.rows[k] ) for k in range( len(self.rows) ) ]

        names = list(self.column_names)

        return Tableau( rows= rows, column_names= names )

hope this will help others