List subclass in Python. Why does the list and empty list not work?

I am puzzled by what, in my opinion, is a very simple and direct subclass of a list in Python.

Suppose I need all the functionality of a list. I want to add several methods to the default list set.

The following is an example:

class Mylist(list): def cm1(self): self[0]=10 def cm2(self): for i,v in enumerate(self): self[i]=self[i]+10 def cm3(self): self=[] def cm4(self): self=self[::-1] def cm5(self): self=[1,2,3,4,5] ml=Mylist([1,2,3,4]) ml.append(5) print "ml, an instance of Mylist: ",ml ml.cm1() print "cm1() works: ",ml ml.cm2() print "cm2() works: ",ml ml.cm3() print "cm3() does NOT work as expected: ",ml ml.cm4() print "cm4() does NOT work as expected: ",ml ml.cm5() print "cm5() does NOT work as expected: ",ml 

Exit:

 Mylist: [1, 2, 3, 4, 5] cm1() works: [10, 2, 3, 4, 5] cm2() works: [20, 12, 13, 14, 15] cm3() does NOT work as expected: [20, 12, 13, 14, 15] cm4() does NOT work as expected: [20, 12, 13, 14, 15] cm5() does NOT work as expected: [20, 12, 13, 14, 15] 

So, it seems that scalar assignment works as I expect and understand. List or snippets do not work, as I understand it. "Doesn't work", I mean that the code in the method does not change the ml instance, as the first two methods do.

What do I need to do to work cm3() cm4() and cm5() ?

+4
source share
3 answers

The problem is that in cm3 , cm4 and cm5 you do not modify the object! You create a new one as part of a member function, and then assign it to yourself. External coverage does not take this into account. In cm1 and cm2 you change the same object, so the object remains the same.

Try using the id function to debug this:

 def cm4(self): self=self[::-1] print 'DEBUG', id(self) ... m1.cm4() print 'DEBUG', id(self) 

You will see that id is different.

So you may ask how to do this? You are lucky to have lists that you can assign in splicing. This may not be so easy with other data structures. What this does is keep the same list, but replace elements. To do this, do:

 self[:] = ... 

So for example:

 self[:] = self[::-1] 
+6
source

Your misunderstanding is that there is something special about the word self . In these methods, this is simply a scope name like any other name in python, so when you reassign it, you simply retype the name self to some other object - you don't mutate the parent object. In fact, this argument does not even need to be called self , it is only an agreement that python programmers use.

Here is the reimplementation of your members for the correct mutation:

 def cm3(self): self[:] = [] def cm4(self): self.reverse() def cm5(self): self[:] = [1,2,3,4,5] 
+4
source

use self[:] instead of self, self = ... will reassign its own variable only to another object that will not change the list object.

 def cm3(self): self[:]=[] def cm4(self): self[:]=self[::-1] def cm5(self): self[:]=[1,2,3,4,5] 
+2
source

Source: https://habr.com/ru/post/1398525/


All Articles