Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to assign a list without changing the address?

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

[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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading