I have a subroutine that is given a list which is used at another part in the program, and the subroutine is to modify that list.
In particular, it is supposed to trim the list.
Let’s say the code looks like this so far:
class Foo:
array = [0,1,2,3,4,5]
def modify(target, length):
array = target.array
array = array[0:length]
foo = Foo()
print(foo.array)
modify(foo, 3)
print(foo.array)
Executing this code will produce the output
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5]
because the line array = array[0:length] creates a new list and the temporary variable array is then simply set to point to a new address.
However, I’d like to find some way in which modify actually changes the object.
Now for this code example, it would be a simple solution to add a line target.array = array. However, in my actual case, the actual class I am dealing with has a side effect for the setter that I want to avoid (I do something like that several times in a row, and each time would render some data which would show states in-between, and also complain about jagged data).
Now the thing is, I could rewrite this particular function into
def modify(target, length):
array = target.array
while(len(array)>length):
array.pop(-1)
since pop doesn’t change the address.
I could also write some helper method like
def copy_into(source: list, target: list)
that is then called like
copy_into(array[0:length], array)
This would be my workaround, but it doesn’t strike me exactly as being elegant, or pythonic. And I’d like to know whether there is a standard way to assign without changing address in general.
Is this possible, and if so, how?
>Solution :
Using slice assignment is one way to do this. A simple example that doesn’t involve a wrapper class (since it’s irrelevant to the subject of the question and the class has other problems that muddy the discussion):
def truncate(array, length):
array[:] = array[:length]
array = list(range(6))
print(array) # [0, 1, 2, 3, 4, 5]
truncate(array, 3)
print(array) # [0, 1, 2]
When you assign to a list’s [:] slice you’re essentially saying "replace the list’s entire contents with the RHS of the assignment". The RHS expression can be a list, a list slice, or any other iterable.