0

I am implementing few list methods manually like append(), insert(), etc. I was trying to add element at the end of list (like append method). This the working code i am using:

arr = [4,5,6]

def push(x, item): 
  x += [item]
  return x

push(arr,7)
print(arr)      #Output: [4,5,6,7]

But when I am implementing same code with little difference. I am getting different output.

arr = [4,5,6]

def push(x, item): 
  x = x + [item]
  return x

push(arr,7)
print(arr)      #Output: [4,5,6]

And I am facing same for insert method. Here is code for insert method:

arr = [4,5,7,8]

def insert(x, index, item): 
  x = x[:index] + [item] + x[index:]
  return x

insert(arr,2,6)
print(arr)      #Output: [4,5,7,8]

I know I can store return value to the list by arr=insert(arr,2,6) but I want an alternative solution, that list automatically gets update after calling function like in my first code sample.

Edit 1: I think x[index:index] = [item] is better solution for the problem.

atultherajput
  • 175
  • 3
  • 18
  • [relevant](https://stackoverflow.com/questions/15376509/when-is-i-x-different-from-i-i-x-in-python) – jacoblaw Jul 18 '17 at 00:20

5 Answers5

3

x += [item] and x = x + [item] are not a little difference. In the first case, you are asking to make a change to the list referenced by x; this is why the result reflects the change. In the second, you are asking to have x reference a new list, the one made by combining x's original value and [item]. Note that this does not change x, which is why your result is unchanged.

Also note that your return statements are irrelevant, since the values being returned are ignored.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
2

In your first example you mutated(a.k.a changed) the list object referred to by x. When Python sees x += [item] it translates it to:

x.__iadd__([item])

As you can see, we are mutating the list object referred to by x by calling it's overloaded in-place operator function __iadd__. As already said, __iadd__() mutates the existing list object:

>>> lst = [1, 2]
>>> lst.__iadd__([3])
[1, 2, 3]
>>> lst
[1, 2, 3]
>>> 

In your second example, you asked Python to assign x to a new reference. The referenced now referrer to a new list object made by combining (not mutating) the x and [item] lists. Thus, x was never changed.

When Python sees x = x + [item] it can be translated to:

x = x.__add__([item])

The __add__ function of lists does not mutate the existing list object. Rather, it returns a new-list made by combing the value of the existing list and the argument passed into __add__():

>>> lst = [1, 2]
>>> lst.__add__([3]) # lst is not changed. A new list is returned.
[1, 2, 3]
>>>

You need to return the the result of the version of push to the arr list. The same goes for insert.

Christian Dean
  • 22,138
  • 7
  • 54
  • 87
  • This is nice info. I wish my Python classes didn't tell me that `x += 1` and `x = x + 1` are the same....since apparently they are not. – coppereyecat Jul 15 '20 at 00:17
  • Yeah @dwllama, functionally I suppose they are the same. But as the OP saw here, there are issues you can run into when you take this functional equivalence to far. – Christian Dean Jul 15 '20 at 20:00
1

You can assign to a slice of the list to implement your insert w/o using list.insert:

def insert(x, index, item):
    x[:] = x[:index] + [item] + x[index:]

this replaces the contents of the object referenced by x with the new list. No need to then return it since it is performed in-place.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
-1

The problem is that you haven't captured the result you return. Some operations (such as +=) modify the original list in place; others (such as x = x + item) evaluate a new list and reassign the local variable x.

In particular, note that x is not bound to arr; x is merely a local variable. To get the returned value into arr, you have to assign it:

arr = push(arr, 7)

or

arr = insert(arr, 2, 6)
Prune
  • 76,765
  • 14
  • 60
  • 81
-1
class DerivedList(list):
    def insertAtLastLocation(self,obj):
        self.__iadd__([obj])        

parameter=[1,1,1]
lst=DerivedList(parameter)
print(lst)   #output[1,1,1]
lst.insertAtLastLocation(5)
print(lst)   #output[1,1,1,5]
lst.insertAtLastLocation(6)
print(lst)   #output[1,1,1,5,6]

You can use this code to add one element at last position of list

class DerivedList(list):
    def insertAtLastLocation(self,*obj):
        self.__iadd__([*obj])

parameter=[1,1,1]
lst=DerivedList(parameter)
print(lst)    #output[1,1,1]
lst.insertAtLastLocation(5)
print(lst)     #output[1,1,1,5]
lst.insertAtLastLocation(6,7)
print(lst)    #output[1,1,1,5,6,7]
lst.insertAtLastLocation(6,7,8,9,10)
print(lst)   #output[1,1,1,5,6,7,8,9,10]

This code can add multiple items at last location

Ahmad
  • 1
  • 1