4

This is my first question on the forum and I'm also really new to Python, so maybe this doesn't make a lot of sense, but I'm just left wondering...

It's very related, but IMO this question Slicing a list in Python without generating a copy does not answer the question of how to slice a list in such a fashion that changing the slice would change the original?

Say, if I want to change only part of a list in a function and make sure that the function doesn't have access to all the members, how do I write this:

def myFunc(aList):
    for i in range(0,len(aList)):
        aList[i] = 0

wholeList = range(0,10)
partOfList = wholeList[3:6]
myFunc(partOfList)

so that the in the end wholeList would be

[0, 1, 2, 0, 0, 0, 6, 7, 8, 9] 

??

I guess this would work if the contents of wholeList were mutable objects, but with numbers is the only way to have the myFunc return the changed list and assign in the calling workspace?

Community
  • 1
  • 1
Juspe
  • 43
  • 6

3 Answers3

4

If you want to modify just a part of the list, you can send in only that slice, and assign the modifications to that same section using return:

def myFunc(aList):
    for i in range(0,len(aList)):
        aList[i] = 0
    return aList

wholeList = range(0,10)
wholeList[3:6] = myFunc(wholeList[3:6])

Otherwise as you said before, you are just creating new lists that happen to reference what is contained in the slice of the original, you'll have to reassign any modifications to the new list back into the old one.

To further clarify, the elements of wholeList[3:6] and partOfList are the same objects. But the lists are just references to those objects. So id(wholeList[3]) == id(partOfList[0]), but if we change one of those references, eg partOfList[0] = 10, then we change the reference of partOfList[0] to 10 not the actual object (3) that was being pointed to. Thus there is no action in this modification that would reflect any changes in wholeList, since it is still referencing the original object..

MrAlexBailey
  • 5,219
  • 19
  • 30
  • Thanks for the clarification. This concept of a list only containing references to actual objects is more or less clear to me... What I think I was really trying to ask is if it is possible to create a `partOfList` that would contain the same references as `wholeList`, but not all of them. Thus enabling to change only part of `wholeList` without an explicit assignment. I guess the answer in short is "no". – Juspe Jul 07 '15 at 17:37
  • @Juspe That's correct, they're just lists of references, modifying one element of a list will not reflect in any other lists **as long as those objects are immutable**. If they are mutable objects, then they can be changed "through the slice" per say. – MrAlexBailey Jul 07 '15 at 17:49
0
You can modify the list directly:
>>> wholeList = range(0,10)
>>> wholeList[3:6] = [0 for _ in range(3)] # or = [0]*3
>>> wholeList
[0, 1, 2, 0, 0, 0, 6, 7, 8, 9]
Kuai
  • 135
  • 7
0

To offer an alternative, this works only in Python 2:

In [2]: a = range(10)
In [3]: a.__setslice__(3,6,[0]*3)

In [4]: a
Out[4]: [0, 1, 2, 0, 0, 0, 6, 7, 8, 9]

However, I'd vote for the solutions other people gave because they are more readable. :))

Hrvoje
  • 362
  • 2
  • 6