0

The following doubt is related to this question but a little different. The answer is not clear to me.

Consider a list x that has to be modified. The following ipython session illustrates the point:

In [1]: x=[]
In [2]: x.append(2)
In [3]: x
Out[3]: [2]
In [4]: x=[] # able to start working on x again
In [5]: x
Out[5]: []

In [6]: def modify(x):
   ...:     x.append(2)
   ...:     print x
   ...:     x=[]   # does not throw errors
   ...:     

In [7]: x=[]
In [8]: x.append(2)

In [9]: x.append(2)
In [10]: x    # x is now a list
Out[10]: [2, 2]

In [11]: modify(x)    # len(s) proportional to the number of times modify is called
[2, 2, 2]

In [12]: x
Out[12]: [2, 2, 2]

if x, a list is a mutable object, why wasn't I able to modify it inside a function but was able to modify it on the command line? I thought it was related to the function being main but:

  In [30]: def modify(x):
      ...:     print __name__
      ...:     x.append(2)
      ...:     print x
      ...:     x=[]
      ...:     x=[1, 5, 7]
      ...:     

the following session shows that name remains unchanged.

  In [36]: print __name__
  __main__

  In [37]: x=[]

  In [38]: modify(x)
  __main__
   [2]
  # why is the name __main__ inside modify?
  In [39]: modify(x)
  __main__
  [2, 2]
wander95
  • 1,298
  • 1
  • 15
  • 22
  • 2
    `x = []` doesn't modify the list, it reassigns the local variable. The original list and global variable are unaffected. – Barmar Dec 26 '17 at 19:38
  • Why was I able to do it on the command line then? What changed? – wander95 Dec 26 '17 at 19:39
  • 1
    Because you don't have a local variable, you're assigning the global variable. – Barmar Dec 26 '17 at 19:40
  • 1
    It might be clearer if you didn't give the function argument the same name as the global variable. Giving them the same name doesn't make them the same variable, because of variable scope. – Barmar Dec 26 '17 at 19:43
  • change `x = []` to `x.clear()` in your function to modify the global object – f5r5e5d Dec 26 '17 at 20:20
  • `AttributeError: 'list' object has no attribute 'clear'` in both cases. – wander95 Dec 26 '17 at 20:22
  • python version difference? - I'm using 3.6 – f5r5e5d Dec 26 '17 at 20:43
  • 1
    looks like it is `del x[:]` in 2.7 – f5r5e5d Dec 26 '17 at 20:50
  • 1
    apparently `del x` is different from `del x[:]` – wander95 Dec 26 '17 at 21:04
  • You have a fundamental misunderstanding about how Python variables work, and particularly, the difference between mutating an object and variable assignment. It's a common hang-up. I suggest reading the following https://nedbatchelder.com/text/names.html which is written by a Stackoverflow legend. – juanpa.arrivillaga Dec 26 '17 at 21:13
  • @wander95 yes. `del x[:]` deletes all the elements in a list, `del x` deletes the *name* `x`, which will decrease the reference count of the list object referred to by `x`. – juanpa.arrivillaga Dec 26 '17 at 21:16

0 Answers0