Multidimensionnal array class and line object in Python
<p>I have a question that spawned from writing my own class to manage a two-dimension table.</p>

<p>I started by creating a simple class as follows, creating an empty_line object that was copied as much as needed to create the number of lines:</p>

<pre><code>class Table(object):
"""Table class, allows the creation of new lines and columns to the table"""
def __init__(self, col = 1, lines = 1, defaultcontent=''):
    self.columns = col
    self.lines = lines
    self.empty_line = [defaultcontent for i in range(self.columns)]
    self.table = [self.empty_line for j in range(self.lines)]

def add_line(self):
    self.table.append(self.empty_line)
    self.lines += 1

def add_column(self):
    self.empty_line.append('')
    for i in range(self.lines):
        self.table[i].append('')
</code></pre>

<p>However, after I created a table, for example with <code>table = Table(5,3)</code>, and do an assignment with <code>table.table[1][2] = 'something'</code>, I realised the <code>'something'</code> found itself in every line, and that I couldn't change a single line without having the others changed. Also, <code>self.empty_line</code> was changed.</p>

<p>After a little while, I wrapped my head around the problem being in the <code>self.empty_line</code> usage. I rewrote my class, this time taking out the <code>self.empty_line</code> and replacing it with the primitive <code>['' for i in range(self.columns)]</code> (and of course also correcting the bug in the <code>add_column()</code> method that would add two columns instead of just one!).</p>

<p>My problem went away, but a question still lingers: Shouldn't the         <code>self.table = [self.empty_line for j in range(self.lines)]</code> create a copy of the <code>self.empty_line</code> object for every new line, instead of somehow 'linking' the same <code>self.empty_line</code> instance (that gets changed).</p>

<p>So what am I doing wrong, and where is the hole in my knowledge about python objects?</p>

<p>In your code:</p>

<pre><code>self.empty_line = [defaultcontent for i in range(self.columns)]
self.table = [self.empty_line for j in range(self.lines)]
</code></pre>

<p>The empty_line is copied in every line of the table using swallow copy. You copied only references, not the default content.</p>

<p>To fix that:</p>

<pre><code>self.table = [[default_content] * self.columns for _ in range(self.lines)]
</code></pre>

<p>Same problem with add_line.
Don't store empty_line but use default_content instead.</p>

<pre><code>self.table.append([self.default_content] * self.columns)
...
</code></pre>

<p>See: <a href="http://stackoverflow.com/questions/28684154/python-copy-a-list-of-lists">Python copy a list of lists</a></p>

python object multidimensional-array