3

I am learning Python and more specifically I am exploring the scoping rules.

I tried the following "experiment":

def increment(n): 
   n += 1 
   print(n)
   return n

n = 1 
increment(n) 
print(n) 

This piece of code outputs: 2 , 1. Should n't it output instead 2, 2 since the variable n is returned to the global environment?

Your advice will be appreciated.

gk7
  • 145
  • 1
  • 2
  • 7
  • `return` doesn't mean "after this, change the scope to global" but that the value of the expression `increment(n)` will then be the local n. So you should do `n = increment(n)`. – syntonym Jan 27 '17 at 11:47
  • [Here](http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference)'s everything you need to know. – Eric Duminil Jan 27 '17 at 11:47
  • 2
    Possible duplicate of [Local and global variables in python functions](http://stackoverflow.com/questions/16865213/local-and-global-variables-in-python-functions) – Mohammad Yusuf Jan 27 '17 at 11:48
  • related: [Why can a function modify some arguments as perceived by the caller, but not others?](https://stackoverflow.com/q/575196/4279) – jfs Aug 21 '18 at 18:43

2 Answers2

5

You have two distinct variables (names) here: one lives in the global scope, the other is local to increment. Rebinding the local one in increment doesn't impact the global one, and the fact that increment returns it's own n has no impact on the global one either (the fact they have the same name is irrelevant). If you want to have the global n pointing to the value returned by increment(), you have to rebind it explicitely:

n = 1
print(n)
n = increment(n)
print(n)
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
-2

Consider the following modification of the snippet above:

def increment(n): 
   n[0] += 1 
   print(n[0])
   return n

n = [1] 
increment(n) 
print(n[0]) 

This prints 2, 2.

In many computer languages (among them Javascript) a difference is made between function parameters that are primitive (like the integers 1 and 2) or compound (like the one-element list n[0]). Usually primitives are passed by value (their values are copied to temporary variables internal to the function). Compound entities are usually not copied, but passed by reference (the address of the entity is passed and the entity is accessed from within the function). If I look at the output of the two code snippets above, it seems to me that Python makes that difference too.

PS After I wrote this I looked at a 2009 Stack Overflow question. A primitive entity is called in the most popular 2009 answer an immutable object and a compound entity is called a mutable object, otherwise my answer is in agreement with the older answer.

P. Wormer
  • 377
  • 3
  • 11
  • 1
    Python doesn't have primitive types, everything's an object, and mutability doesn't map well (a tuple is an immutable compound entity, for example). Also all arguments are passed by object reference, neither value nor reference: https://stackoverflow.com/a/33066581/3001761 – jonrsharpe Jul 15 '17 at 09:53
  • Being new to Python I would like to know how one can rationalize the difference in calling the function increment() with the scalar n or the with the list [n]. The difference is undeniable, either 2,1 or 2,2 is printed. Jonrsharpe, do you know how to explain this? – P. Wormer Jul 16 '17 at 08:37
  • 1
    You're literally doing different things. In one you're mutating a mutable data structure: `n[0] = n[0] + 1` (note that it's unconventional to return something when you mutate the argument). In the other you're reassigning the name from one immutable object to another, new immutable object: `n = n + 1`. – jonrsharpe Jul 16 '17 at 09:24
  • -1 As already observed, this answer isn't correct. The analog to the original post would be reassigning `n` to a new list, `n = [2]` within `increment` (in place of `n[0] += 1`). This will also output `2`, `1`, consistent with the original post. – Andrew Palmer Apr 25 '19 at 18:26