1

I have this function that should transpose the list it gets. This works, but for some reason it alters the original matrix as well: why?

Matrix = [["1"], ["1","2"], ["1","2","3","4"], []]

def test():
    global Matrix # same happens when global or not
    tMatrix = Matrix
    print(tMatrix) # 1
    tMatrix = transposer(Matrix)
    print(tMatrix) # 2
    print(Matrix) # 3

Output:

[['1'], ['1', '2'], ['1', '2', '3', '4'], []]   # 1
[['1', '1', '1'], ['2', '2'], ['3'], ['4']]     # 2
[[], [], [], []]                                # 3

I think it should not matter, but here is the transposer function:

def transposer(m):
    tm = []
    maxi = 0
    for i in range(0, len(m)):
        maxi = max(maxi, len(m[i]))
    for z in range(0, maxi):
        row = []
        for j in range(0, len(m)): 
            try:
                row.append(m[j].pop(0))
            except:
                pass
        tm.append(row)
    return(tm)

How is it possible that the Matrix variable is also affected even though the function is not called on that variable?

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
PascalVKooten
  • 20,643
  • 17
  • 103
  • 160

1 Answers1

1

When you do

tMatrix = Matrix

in reality you are making tMatrix a reference to the original Matrix object. So, when you assign the output of the transposer function back to tMatrix you are really changing the original Matrix object itself. This is a very common misunderstanding when you're getting used to python, like you can see here, for example (the answer is worth reading too).

Try to read something on the way Python treats assignments and you'll see the difference from other languages:

http://learnpython.pbworks.com/w/page/15956522/Assignment

http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/variables.html

EDIT:

To solve the problem, you can make a copy of the original object passed to transpose through a copy operation:

def transposer(n):
    m = copy.copy(n)
    tm = []
    maxi = 0
    for i in range(0, len(m)):
        maxi = max(maxi, len(m[i]))
        print i, maxi
    for z in range(0, maxi):
        row = []
        for j in range(0, len(m)): 
            try:
                row.append(m[j].pop(0))
            except:
                pass
        tm.append(row)
    return(tm)

Just as a sidenote, you're treating your elements as strings. If they were supposed to be numeric you can just enter them without the " ". Also, if you don't need to use your own transposing algorithm, you can just use the NumPy package, which already does matrix transposition.

Community
  • 1
  • 1
Claudio
  • 2,191
  • 24
  • 49
  • Might you have a solution for what to do instead? I understand that it is a reference like I saw in C++, but there it is an option to refer to the binding. – PascalVKooten Aug 11 '13 at 18:12
  • The problem is in the transpose function. When you do `m[j].pop(0)` you are deleting elements from the original `Matrix`, which was passed through `m`. I'm editing my answer so it does it right. – Claudio Aug 12 '13 at 12:42
  • I found this "copy.deepcopy" from the copy module. I had no idea it was actually popping that was having that side-effect! Thanks. – PascalVKooten Aug 12 '13 at 13:01