I am befuddled over what I think is a very simple and straight forward subclass of a list in Python.
Suppose I want all the functionality of list. I want to add several methods to the default set of a list.
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
The output:
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 a scalar assignment works as I expect and understand. List or slices do not work as I understand. By 'does not work,' I mean that the code in the method does not change the instance of ml as the first two methods do.
What do I need to do so that cm3()
cm4()
and cm5()
work?
The problem here is that in cm3
, cm4
, and cm5
, you are not modifying the object! You are creating a new one in the scope of the member function, and then assigning it to self. The outer scope doesn't respect this. In cm1
and cm2
, you are modifying the same object, so the object stays 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'll see that the id
is different.
So, you might ask, well how do I do this? You are lucky that with lists you can assign into a splice. This might not be as easy with other data structures. What this does is keeps the same list, but replaces the items. To do this, do:
self[:] = ...
So, for example:
self[:] = self[::-1]
Your misunderstanding is that there is something special about the word self
. In those methods it is just a name in scope like any other name in python, so when you reassign it, you are just rebinding the name self
to some other object - not mutating the parent object. In fact that argument doesn't even need to be named self
, that is only a convention that python programmers use.
Here is reimplementation of your members to mutate properly:
def cm3(self):
self[:] = []
def cm4(self):
self.reverse()
def cm5(self):
self[:] = [1,2,3,4,5]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With