-4

I thought that all python variables were local. However, I found out that this is not the case for lists. Which is very dangerous in my opinion.

This piece of code :

def f(piano):
    piano[1]=3
    print(piano)
pizza=[1,2]
f(pizza)
print(pizza)

Outputs:

[1,3]
[1,3]

While if a list were local it should have been:

[1,3]
[1,2]

Anybody knows why this is the case?

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
ThaNoob
  • 520
  • 7
  • 23
  • 5
    python lists are **mutable**. you are changing the contents of your list `pizza`. this has nothing to do with the scope of variables. – hiro protagonist Jan 21 '18 at 20:14
  • 1
    This has nothing to do with variable scope. – Matt Ball Jan 21 '18 at 20:14
  • "I thought that all python variables were local" well, that isn't true, but your list *is* local in the function in this case, so that isn't the issue. – juanpa.arrivillaga Jan 21 '18 at 20:14
  • if you want to have a "detached" copy of your list, search SO for `python deepcopy, shallowcopy` - lots of threads, f.e. this one : https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list - you just need to know when a _shallow copy_ ( f.e. `[:]`) is enough (essentially if you list does NOT contain other mutables) and when to _deep copy_ ( i.e. lists of lists which are mutable). – Patrick Artner Jan 21 '18 at 20:18
  • You seem to be unclear on the interaction between variables and objects. Have a [quick guide](https://nedbatchelder.com/text/names.html) to how that stuff works. – user2357112 Jan 21 '18 at 20:25
  • thanks for the quick replies, obviously I don't know my python theory very well. I thought that mutable just meant that you could change values inside your list, something you can't do with tuples who are immutable. So is it correct to say that if a list is passed to a function that no copy is made but that it is still the original list? – ThaNoob Jan 21 '18 at 20:28
  • A small, non technical question, should I delete this question now since it has downvotes? – ThaNoob Jan 21 '18 at 20:29
  • @ThaNoob that is what immutable means. Anyway, when something is passed to a function, **anything**, not just lists, a copy is never made. – juanpa.arrivillaga Jan 21 '18 at 20:31
  • I suggest reading this: https://nedbatchelder.com/text/names.html – juanpa.arrivillaga Jan 21 '18 at 20:32

1 Answers1

0

Well, technically, you're right in that the piano variable is local. However, it still points to the same internal reference as pizza.

This is what's happening behind the scene:

You allocate a new list of values, and a variable named pizza is created so you can refer to it:

pizza -> [ 1 , 2 ]

When you assign this variable to another variable, only the pointer to the reference is copied, but the reference itself remains.

 other_var = pizza

 other_var -
            |
 pizza -----|--> [ 1 , 2 ]

So, when you pass in pizza to the function f technically, you are just copying only the pointer to the same list, and creating a different named variable to reference.

Yes, this newly created variable can only be accessed within the f scope, so yes, it's local. But if you mutate its reference in any way, it'd be as if you were mutating pizza itself as they both point to the same object.

Matias Cicero
  • 25,439
  • 13
  • 82
  • 154
  • thanks, that clarifies a lot but why is this not the case for normal variables? If in my code pizza wouldn't have been a list but the int 2 and I than changed piano in the int 3, then it would print first 3 and then 2 as I would expect it to do. – ThaNoob Jan 21 '18 at 20:34
  • 3
    @ThaNoob this is the case **with every variable**. All variables act **exactly the same**. You just cannot mutate an `int` object. Assignment is **not mutation**. Check out: https://nedbatchelder.com/text/names.html – juanpa.arrivillaga Jan 21 '18 at 20:35
  • Thanks, I got it I think. When I give piano the value int 3 than I'm actually deleting the old pointer piano, and I'm making a new pointer piano that points to another memory space. While for the list I'm still maintaining the same pointer, pointing to the same memory space but the value in the memory space has changed. And if the value in the memory space of an object can be changed while maintaining the same pointer than that object is mutable and otherwise it is not. Does this make sense? – ThaNoob Jan 21 '18 at 20:45