2

My question is will the init method of list class calling other method such as append or insert to achieve its functionality.

like:

class test(list):

def __init__(self,values):
    super().__init__()

def append(self, value):
    self.append(value + 1)

I want:

x = test([1,2,3])
x
[2,3,4]

but I got:

[1,2,3]

I know I can make it work by overload init itself.

def __init__(self,values):
    super().__init__([x+1 for x in values])

Can I just overload some basic value insert method like setitem, so all the insert operation like append, insert will call it, and therefore have that addition effect.

thanks for any suggestion.

Jians
  • 45
  • 4

2 Answers2

4

list.__init__ does not call any overrideable method. It makes a direct, un-overrideable call to the C function that implements the extend method:

if (arg != NULL) {
    PyObject *rv = listextend(self, arg);
    if (rv == NULL)
        return -1;
    Py_DECREF(rv);
}

This is the case for most methods of most Python types implemented in C.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • So, I have to overload all the element inserting method to achieve the addition functionality? Including append, insert and extend? That's sad news. Thank you anyway. – Jians Jun 07 '17 at 16:51
  • @Jians: I find it beats the usual situation, where you have no idea what overrides will affect or interfere with what other methods. People don't do enough to think about or document the API they provide to subclasses. – user2357112 Jun 07 '17 at 16:53
  • For those people whose daily work is not programming, find the exact document is really a tough work. And that's why stackoverflow is the best place to learn from experienced expert. – Jians Jun 07 '17 at 17:08
0

I've seen another example overriding form collections.MutableSequencethat would let you get this functionality. I'm not sure if this is more convenient than your initial idea, but it will increment any numbers during __init__, append, insert, and extend

class IncList(collections.MutableSequence):
    def __init__(self, int_list):
        self._list = []
        for el in int_list:
            self.append(el)

    def __len__(self): return len(self._list)
    def __getitem__(self, item): return self._list[item]
    def __delitem__(self, item): del self._list[item]

    def __setitem__(self, index, value):
        self._list[index] = value + 1

    def insert(self, index, value):
        self._list.insert(index, value + 1)

    def __str__(self):
        return str(self._list)

    def __repr__(self):
        return "%s(%r)" % (self.__class__, self._list)


> l = IncList([1, 2, 3])
> print(l)
[2, 3, 4]
> l.append(4)
> print(l)
[2, 3, 4, 5]
> l[0] = 0
> print(l)
[1, 3, 4, 5]
> l.extend([5, 6])
> print(l)
[1, 3, 4, 5, 6, 7]
> l.insert(1, 1)
> print(l)
[1, 2, 3, 4, 5, 6, 7]

See this answer for more information.

Tom Sitter
  • 1,082
  • 1
  • 10
  • 23
  • That's the way I was looking for! What's the difference between MutableSequence and built in list? Are they essentially same? – Jians Jun 08 '17 at 00:40
  • I'm no expert, but that's my understanding. MutableSequence is an abstract base class that inherits from Sequence and implements all of the same methods as list. – Tom Sitter Jun 08 '17 at 01:11
  • Thanks a lot ! It really helps. – Jians Jun 08 '17 at 01:13
  • @Jians one caveat is that this implementation will increment moved items when `l.reverse()` is called. Sorting doesn't seem to be a problem though – Tom Sitter Jun 08 '17 at 01:16
  • got it, sort is not really problem – Jians Jun 08 '17 at 01:19