Looping over list to delete items - unexpected behavior

165 Views Asked by At

A simplified scenario that's not working as expected. I'm hoping someone can point out why.

nums = [0, 0, 4, 0]
new_list = nums
for i in range(len(nums)):
  if nums[i] !=0:
    break
  del new_list[0]
new_list

I'm trying to remove preceding zeroes. I expect the above loop to delete the first element of the list until it encounters a non-zero number, then break. It's only deleting the first zero, even though my del new_list[0] statement is in the loop.

Expected output: [4, 0] Actual output: [0, 4, 0]

3

There are 3 best solutions below

1
On BEST ANSWER

The assignment operator in python (as used in new_list = nums) does not create a new object but just assigns another name to the existing object. Any changes you make to nums will also affect new_list.

To create a new object, you can make a shallow copy instead:

new_list = nums.copy()
3
On
nums = [0, 0, 4, 0]
new_list = nums # this refer to nums and when you change new_list, nums changes
# do following to make a copy.
new_list = nums[::]
for i in range(len(nums)):
  if nums[i] !=0:
    break
  del new_list[0]
new_list

Output

[4, 0]
0
On

In python, assignment operator doesn't make you a new instance of your object, in your casenums. I suggest you to read about deep copy and shallow copy in python. As this article says

In Python, Assignment statements do not copy objects, they create bindings between a target and an object. When we use = operator user thinks that this creates a new object; well, it doesn’t. It only creates a new variable that shares the reference of the original object. Sometimes a user wants to work with mutable objects, in order to do that user looks for a way to create “real copies” or “clones” of these objects. Or, sometimes a user wants copies that user can modify without automatically modifying the original at the same time, in order to do that we create copies of objects.

You can make a deep copy using the copy module.

import copy


nums = [0, 0, 4, 0]  
new_list = copy.deepcopy(nums) # using deepcopy for deepcopy