Create a subclass of list without deep copy
<p>I want to subclass <code>list</code> to add some function to it, for example, <code>my_func</code>. </p>

<p>Is there a way to do this without copying the whole list, i.e. make a shallow copy, on the creation of the <code>MyList</code> object and let <code>MyList</code> reference the same list as the one used to construct it?</p>

<pre><code>class MyList(list):
    def my_func(self):
        # do some stuff
        return self


l1 = list(range(10))
l2 = MyList(l1)

print(l1)
print(l2)

l1[3] = -5

print(l1)
print(l2)
</code></pre>

<p>Pretty sure this isn't possible with a <code>list</code> subclass. It <em>is</em> possible with a <strong><a href="https://docs.python.org/3/library/collections.html#collections.UserList" rel="nofollow"><code>collections.UserList</code></a></strong> subclass (simply <em><a href="https://docs.python.org/2.7/library/userdict.html#module-UserList" rel="nofollow"><code>UserList</code></a></em> in Python <code>2</code>):</p>

<pre><code>from collections import UserList

class MyList(UserList):

    def __init__(self, it=None):
        # keep reference only for list instances
        if isinstance(it, list):
            self.data = it
        else:
            super().__init__(it)

    def my_func(self):
        # do some stuff
        return self
</code></pre>

<p>The fact that <code>UserList</code> exposes a <a href="https://docs.python.org/3/library/collections.html#collections.UserList.data" rel="nofollow"><strong><code>data</code></strong></a> attribute containing the actual list instance makes it easy for us to replace it with the iterable <code>it</code> and essentially just drop the supplied argument there and <em>retain the reference</em>:</p>

<p>By initializing as you did: </p>

<pre><code>l1 = list(range(10))
l2 = MyList(l1)

print(l1, l2, sep='\n')
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
</code></pre>

<p>and then mutating:</p>

<pre><code>l1[3] = -5
</code></pre>

<p>The <code>data</code> attribute referencing <code>l1</code> is, of course, mutated:</p>

<pre><code>print(l1, l2, sep='\n')
[0, 1, 2, -5, 4, 5, 6, 7, 8, 9]
[0, 1, 2, -5, 4, 5, 6, 7, 8, 9]
</code></pre>

python list python-3.x oop inheritance