0

Using the following code

def test(n): 
    n=n*2 
    print("inside test",n) 

n=[9] 
print("before the call", n) 
test(n) 
print("after the call", n) 

the ouput is:

before the call [9]
inside test [9, 9]
after the call [9]

I thought that the passing of list parameters in functions was made by reference and modified the calling parameters.It is not the case here: suprising. I was expecting:

before the call [9]
inside test [9, 9]
after the call [9, 9]

If I use the append method instead of n=n*2, the effect is OK. Can anyone clarify this point, please?

Hana
  • 101
  • 10
  • sorry, I was expecting: before the [9] inside test [9, 9] after the call [9,9] – Hana Dec 13 '16 at 12:34
  • Try with `n.append(9)` – S. de Melo Dec 13 '16 at 12:40
  • See [this](http://nedbatchelder.com/text/names.html) and [this](http://effbot.org/zone/call-by-object.htm). – Daniel Roseman Dec 13 '16 at 12:42
  • Can you clarify the question? Your expectation is same as your output... Are you trying to multiply every element in the list by 2? If so, you'll need to do a list comprehension like this: output = [element * 2 for element in my_list] – Boon Dec 13 '16 at 12:42
  • Sorry my expectation was: before the call [9] inside test [9, 9] after the call [9, 9] – Hana Dec 13 '16 at 12:44
  • In fact I want to understand how really parameters like list are handle in Python? – Hana Dec 13 '16 at 12:47
  • @Hana fix the question with what you actually expect. Will avoid confusion – Nath Dec 13 '16 at 12:49
  • Parameters "like lists" are handled in *exactly* the same way as any other parameters. Read those two references I posted. – Daniel Roseman Dec 13 '16 at 12:50

4 Answers4

2

It's about mutable or immutable type and value or reference parameter. Python pass "reference" but not really ( here for for details : https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/)

>>> def update_list(the_list):
    print('got', the_list)
    the_list.append('four')
    print('changed to', the_list)

>>> toto = ["one"]
>>> update_list(toto)
got ['one']
changed to ['one', 'four']
>>> print(toto)
['one', 'four']


>>> def new_list(the_list):
    print('got', the_list)
    the_list = the_list + ["four"]
    print('changed to', the_list)

>>> toto = ["one"]
>>> new_list(toto)
got ['one']
changed to ['one', 'four']
>>> print(toto)
['one']

Python documentation : https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference

A similar question : How do I pass a variable by reference?

Community
  • 1
  • 1
PyNico
  • 695
  • 5
  • 21
1

This line n = n*2, creates a new local variable n inside your test() function, that's why the outside one is not changed. Take a look at these examples:

>>> def test(n):
...     print(id(n))
...     n = n*2
...     print(id(n))
...     print("inside test", n)
...
>>> def test2(n):
...     print(id(n))
...     n.append(2)
...     print(id(n))
...     print("inside test2", n)
...
>>> n = [9]
>>> id(n)
49744472
>>>
>>> test(n)
49744472
49744752
('inside test', [9, 9])
>>>
>>> test2(n)
49744472
49744472
('inside test2', [9, 2])

Inside test(), we have 2 different ids: 49744472 for the param n and 49744752 for the local variable n. In test2() function the same id is printed, which means the same param n is changed inside the function.

ettanany
  • 19,038
  • 9
  • 47
  • 63
0

In python, generally it is confusing to refer to arguments being passed to function as either pass by value/pass by reference.

n=[9]

The above statement binds n to a List object containing single element of value 9. (i.e. [9] in this case)

When n = n * 2 This creates a new List and bound to a variable which is local to the scope of the function.

apatniv
  • 1,771
  • 10
  • 13
0

In n = n*2 creates a local variable inside test function, return n and assign it to n with the results

def test(n): 
    n=n*2 
    print("inside test",n) 
    return n

n=[9] 
print("before the call", n) 
n = test(n) 
print("after the call", n) 

Output:

('before the call', [9])
('inside test', [9, 9])
('after the call', [9, 9])
ignacio.saravia
  • 328
  • 1
  • 4
  • 15