Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie
Hi there,
There is an issue with role permissions that is being worked on at the moment.
If you are having trouble with access or permissions on regional forums please post here to get access: https://www.boards.ie/discussion/2058365403/you-do-not-have-permission-for-that#latest

Trouble returning a list in Python

  • 12-06-2011 12:53am
    #1
    Closed Accounts Posts: 1,312 ✭✭✭


    Hey guys, been teaching myself some Python, and I've encountered a problem that's got me stumped. I think I'm just missing something small, but maybe somebody can point me in the right direction.

    I'm working through some exercises that involve manipulating lists at the moment, and one of them involves creating a set of functions to deal with matrices. Here's what I've got so far:
    def make_matrix(rows, columns):
        matrix = []
        for row in range(rows):
            matrix += [[0] * columns]
        return matrix
    
    
    def add_row(matrix):
        new_matrix = matrix[:]
        new_matrix += [[0] * len(new_matrix[0])]
        return new_matrix
    
            
    def add_column(matrix):
        new_matrix = matrix[:]
        for element in new_matrix:
            element += [0]
        return new_matrix
    
    I'm trying to have the add_column and add_row functions return a new matrix with an extra row/column, without changing the original.

    The add_row function seems to work fine, but I just can't get add_column to do what I want. I'll show you what I mean. When I test it in the interpreter, this is what I get:
    >>> from matrices import *
    >>> m = make_matrix(2, 2)
    >>> m
    [[0, 0], [0, 0]]
    >>> add_row(m)
    [[0, 0], [0, 0], [0, 0]]
    >>> m
    [[0, 0], [0, 0]]
    >>> add_column(m)
    [[0, 0, 0], [0, 0, 0]]
    >>> m
    [[0, 0, 0], [0, 0, 0]]
    
    It adds a column, but it does it by changing the original list. I can't see where in the function this is happening. Can anyone point me in the right direction?

    Thanks!


Comments

  • Registered Users, Registered Users 2 Posts: 1,393 ✭✭✭Inspector Gadget


    Essentially, the matrix you're designing is a list of lists. You're deep copying the main list (the list of rows, essentially), but you're copying references to the column data. That means that the column data is not copied but referenced, which is why the original gets destroyed/changed.

    Have a look at this and see what makes sense, it works for me. The add_column function has been changed a bit. I'm sure there are prettier ways of doing it, but hey:
    def make_matrix(rows, columns):
        matrix = []
        for row in range(rows):
            matrix += [[0] * columns]
        return matrix
    
    def add_row(matrix):
        new_matrix = matrix[:]
        new_matrix += [[0] * len(new_matrix[0])]
        return new_matrix
    
    def add_column(matrix):
        new_matrix = []
        for element in matrix:
            new_matrix += [element[:] + [0]]
        return new_matrix
    

    iPython (nice command line tool for messing with Python) output from same:
    In [2]: m = make_matrix(3, 3)
    
    In [3]: m
    Out[3]: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
    
    In [4]: q = add_column(m)
    
    In [5]: q
    Out[5]: [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
    
    In [6]: m
    Out[6]: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
    
    In [7]: r = add_row(q)
    
    In [8]: m
    Out[8]: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
    
    In [9]: q
    Out[9]: [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
    
    In [10]: r
    Out[10]: [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
    

    Also, NumPy is very good with matrices, if you don't feel like re-inventing the wheel for linear algebra stuff.

    Hope that helps,
    Gadget


  • Closed Accounts Posts: 1,312 ✭✭✭Daftendirekt


    Thanks a million! That had me scratching my head for ages last night. Makes sense to me now, though (I think, anyway!).

    Just gave it a quick test, and it seems to work fine.

    Thanks again.

    Edit: Actually, just looking over it again, there's one thing I'm not quite sure about.
    for element in matrix:
        new_matrix += [element[:] + [0]]
    

    Is 'element[:]' creating a clone of the element here (as in, actually copying it, rather than creating a reference)? I thought 'element[:]' generally meant 'everything in element'.


  • Registered Users, Registered Users 2 Posts: 1,393 ✭✭✭Inspector Gadget


    Well, the revised routine starts off with an empty output matrix, then iterates through the existing one, and adds a zero to the end of a deep copy of the current row, adding the result of that addition (as a list) to the output matrix. If I didn't wrap that whole thing in square brackets you'd end up with a single list...

    Does that help?


  • Closed Accounts Posts: 1,312 ✭✭✭Daftendirekt


    Well, the revised routine starts off with an empty output matrix, then iterates through the existing one, and adds a zero to the end of a deep copy of the current row, adding the result of that addition (as a list) to the output matrix. If I didn't wrap that whole thing in square brackets you'd end up with a single list...

    Does that help?

    Yeah, it does... I get it now.
    Cheers for your help!


  • Registered Users, Registered Users 2 Posts: 297 ✭✭stesh


    Thanks a million! That had me scratching my head for ages last night. Makes sense to me now, though (I think, anyway!).

    Just gave it a quick test, and it seems to work fine.

    Thanks again.

    Edit: Actually, just looking over it again, there's one thing I'm not quite sure about.
    for element in matrix:
        new_matrix += [element[:] + [0]]
    

    Is 'element[:]' creating a clone of the element here (as in, actually copying it, rather than creating a reference)? I thought 'element[:]' generally meant 'everything in element'.

    By simply assigning one variable to another, you are passing around a reference to a single object:
    >>> mylist = [1,2,3,4,5]
    >>> otherlist = mylist
    >>> otherlist is mylist
    True
    


    [:], however, creates a new object representing a copy of the original list, rather than just a reference to it:
    >>> mylist = [1,2,3,4,5]
    >>> otherlist = mylist[:]
    >>> otherlist is mylist
    False
    


  • Advertisement
Advertisement