-1

I was adding and removing elements to an array reference within a method, and i found that though the elements were getting added to the array in reference but it was not getting removed.

def check(arr):
    arr.append(1)
    arr = arr[:-1]

arr = [1]
check(arr)
print(arr)

gives the output [1, 1] I want to know why arr = arr[:-1] not removing from the referenced array

EDIT: a lot of people are posting the correct solution, I am not looking for a solution, instead an explanation of why and how python creates a local variable instead of overwriting the global scope and how does it maintain the two by the same name !

isnvi23h4
  • 1,910
  • 1
  • 27
  • 45
  • `arr = arr[:-1]` This creates a _new_ local variable named `arr`. It does not affect the original argument. – John Gordon Jan 15 '22 at 16:15
  • `arr[:] = arr[:-1]` or *(for this particular case)* `del arr[-1]` – Olvin Roght Jan 15 '22 at 16:18
  • You don't have an [`array`](https://docs.python.org/3/library/array.html) but a [`list`](https://docs.python.org/3/library/stdtypes.html#list). Those two are different. – Matthias Jan 15 '22 at 16:23

3 Answers3

3

As I've already pointed in this comment, if you need in-place list modification, you can apply slice notation:

def check(arr):
    arr.append(1)
    arr[:] = arr[:-1]

But in fact this code will just remove last item (which you have added one line above), so you can just use del:

def check(arr):
    arr.append(1)
    del arr[-1]
Olvin Roght
  • 7,677
  • 2
  • 16
  • 35
  • As I have commented on the other answer, can you give an explanation on how python creates a local copy instead of overwriting the global value, how can the local and global be accessed differently ? is this is what is known as the mutable and immutable in python ? – isnvi23h4 Jan 15 '22 at 18:09
  • 1
    @isnvi23h4, most of information you can find in official tutorial: [9.2. Python Scopes and Namespaces](https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces). Long story short, when you pass list as argument to function, you pass a variable which contains a reference to this list, so changing value of this variable to another reference does not affect content of list which have been originally passed. But when you're using slice notation, it works with list object itself, so modification happens. – Olvin Roght Jan 15 '22 at 18:17
  • 1
    @isnvi23h4, also take a look on this FAQ: [How do I write a function with output parameters (call by reference)?](https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference). Check [accepted answer](https://stackoverflow.com/a/986145/10824407) of next question: [How do I pass a variable by reference?](https://stackoverflow.com/q/986006/10824407). Similar questions: [python; modifying list inside a function](https://stackoverflow.com/q/22054698/10824407), [Python modifying list within function](https://stackoverflow.com/q/27264526/10824407) – Olvin Roght Jan 15 '22 at 18:22
2

Alternatively it can be done with a global variable:

def check_arr():
    global arr
    arr.append(1)
    arr = arr[:-1]

arr = [1]
check_arr()
print(arr)
  • Although the solution would work, using the global keyword in python should be avoided to keep the global scope as clean as possible. https://www.python.org/dev/peps/pep-0008/#global-variable-names or https://stackoverflow.com/questions/19158339/why-are-global-variables-evil. – Wrench56 Jan 15 '22 at 16:27
  • @Wrench56 you're right. It's just an example. For educational purposes rather. – yetanothercoder Jan 15 '22 at 16:31
0

You don't return anything. The arr in the function is in local scope, so the global scope arr won't update

def check(arr):
    arr.append(1)
    return arr[:-1]

arr = [1]
arr = check(arr)
print(arr)
Wrench56
  • 290
  • 2
  • 14