0

Please help me as I am new to python when I call this function the original value of list1 changes

def mystery(list1):
  list1[0] , list1[1] = list1[1], list1[0]

list1 = [7,82,44,23,11]
mystery(list1)
print(list1) #prints [82, 7, 44, 23, 11]

how it can change the value of global list1 if I change my function to

def mystery(list1):
  list1 = list1 + list1[2:5]

then I am getting the global value of list1 and not the updated one.

Austin
  • 25,759
  • 4
  • 25
  • 48
Nihar Shah
  • 13
  • 1
  • 4
  • 1
    How about a `return` at end of function to pass the updated value back to caller? – Austin Feb 12 '19 at 08:28
  • yes, but I am confused about local and global variables in python, here in the first function the value of list1 is changed to new list1 without returning. but in the second function it remains the same. – Nihar Shah Feb 12 '19 at 08:31
  • 1
    `list1 = list1 + list1[2:5]` creates a new list object `list1` whose visibility is only within the function. When you refer to `list1` outside, you access to older `list1`. Here, `list1[0] , list1[1] = list1[1], list1[0]`, the same list object is updated and that's why you see updated value at the output. – Austin Feb 12 '19 at 08:36
  • Thanks, @Austin I got it. – Nihar Shah Feb 12 '19 at 08:40
  • Maybe it can help https://www.python-course.eu/global_vs_local_variables.php. – J Agustin Barrachina Feb 12 '19 at 08:42

5 Answers5

2

lists are mutable objects in python, so if you are passing to a function a list all the changes that you make to the list inside your function will be reflected everywhere/globally

If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart's delight, but if you rebind the reference in the method, the outer scope will know nothing about it, and after you're done, the outer reference will still point at the original object.

If you pass an immutable object to a method, you still can't rebind the outer reference, and you can't even mutate the object.[more details here]

kederrac
  • 16,819
  • 6
  • 32
  • 55
1

Maybe just return the list?

def mystery(list1):
    return list1 + list1[2:5]

list1 = [7,82,44,23,11]
list1 = mystery(list1)
print(list1)
Tempo810
  • 160
  • 7
1

The reason list1 is changing is because you're actually modifying the list object inside of the function.

It really has nothing todo with global / local variables, if you renamed the parameter inside your function to something else, and still passed in list1, list1 would be modified.

If you're wanting to return a new list, you need to first create a copy of the list, there's many ways to do this. list(list1) is one way. Then return the list at the end of the function.

If I understand your queston, you want to actually append some more values to the passed in list, use list1.append(...) to add to the end of the list.

And since you're modifying the list itself, it'll change in the larger scope.

But it's still not using the global scope, as you're just using a var with the same name in the local scope.

Tonis F. Piip
  • 776
  • 2
  • 6
  • 16
1

In python, assigning a value to a variable like a = 5 means you are creating an object in the memory for the value 5. Now a is a link to that object holding 5 (in Layman's terms). If you change a now, say a = "something else", this creates a new object for the string "something else" in somewhere else in the memory and now a is pointing to that. This is why you get to change the data type of python variables.

When you pass something to a python function, that link is the one that is passed on. So when you call mystery(list1), original link to the list1 is passed. Therefore changing an element in the list1 means you are assigning a new value to that particular element in the original list1. No matter you are inside or outside of the function mystery() in this case since you will be using the original link you created to access the element inside list1 to change it. The change happens inside the list1; list1 didn't get reassigned.

However when you do list1 = "something new" inside your function mystery(), you are creating a new variable list1 inside the function which is local to the function. You are not changing the original list1.

Teshan Shanuka J
  • 1,448
  • 2
  • 17
  • 31
0

Passing mutable objects into a function and then modifying the object inside the function will have the same effect as modifying the object directly.

list1 = [1,2,3]

def func(list1):
    list1[0] = 5

>>>list1
[5,2,3]

This is effectively same as directly running list1[0] = 5

However if you pass an immutable object into a function such as tuple, It will not support item assignement TypeError: 'tuple' object does not support item assignment. So you need to build a new immutable object and return it.

>>> tup1 = (1,2,3) # doing tup1[0] = 5 will cause TypeError
>>> tup2 = tup1 + (5,)
>>> tup2
(1, 2, 3, 5)

Put it in function,

>>> def func2(tup1):
        return tup1 + (5,)

>>> func2(tup1=(1,2,3))
(1, 2, 3, 5)
Vineeth Sai
  • 3,389
  • 7
  • 23
  • 34