self
is just another variable. Method objects cause the current instance to be assigned to that name (just like other values are assigned to other function parameters), but like other names, assigning to them will only change what object the name refers to. Other names that reference the same object, like x
, do not change along.
That's because names in Python code are just like tags, and self = <something else>
is like taking the tag of the old instance and putting it on another object. Any other tags still attached to the old object are not moved! Because x
still references the old instance, it is not going to see that you put the self
tag on another object.
Either your update()
method needs to return the new object (so that the caller can update their reference to point to the new object), or change the list in-place (at which point all references to the object will see the same change.
Returning the object means the caller is responsible for doing something with the return value:
class test(list):
def update(self):
return test(['a','b','c','d'])
x = test([1,2,3])
x = x.update() # re-bind `x` to point to the new object.
print(x)
Or you can assign to indices of the list itself; this changes what the contents of the list point to. You can use self
just like any other reference, so x[0] = 5
would change index 0, so would self[0] = 5
. And if you assign to a slice you can change multiple indices at once. The identity slice, [:]
, lets you change all indices at once, and you can assign more or fewer values to grow or shrink a list. Assigning to self[:]
changes all indices, and lets you change all indices to point to any number of different values.
So:
class test(list):
def update(self):
self[:] = ['a', 'b', 'c', 'd']
x = test([1,2,3])
x.update()
print(x) # The x reference to the same list will see the change too
The above replaces all indices with the values in the other list. All references to the instance will see the change; both as self
and x
, and any other such references.
Demo of what this means:
>>> class test(list):
... def update(self):
... self[:] = ['a', 'b', 'c', 'd']
...
>>> x = test([1, 2, 3])
>>> y = x # another reference to the same object
>>> x
[1, 2, 3]
>>> y
[1, 2, 3]
>>> x.update() # update the list in-place
>>> x # visible here
['a', 'b', 'c', 'd']
>>> y # and here!
['a', 'b', 'c', 'd']