Computer Science · Ch 9 — Lists
List as Argument to a Function
List as Argument to a Function
When a list is passed as an argument to a function, what we actually pass is a reference to the list — not a fresh copy of it. Two scenarios must therefore be considered, and they behave very differently.
Scenario (A): the function changes the list's elements — changes ARE reflected back
If the function modifies the elements of the parameter list in place (by index assignment, append(), etc.), it is modifying the very same list object the caller holds, so the changes are visible in the calling code after the function returns.
The program below passes a list of numbers to a function addBonus() that raises every element by 5. The id() function is used to print each list's identity — the fact that the id is the same inside and outside the function proves both names refer to one object. (The actual id number varies from run to run; what matters is that the two printed values match.)
# Function to increment the elements of the list passed as argument
def addBonus(inner):
for i in range(0, len(inner)):
inner[i] += 5 # 5 added to each element, in place
print('Reference of list inside function', id(inner))
# end of function
marks = [40, 55, 70, 85, 90] # create a list
print('Reference of list in main', id(marks))
print('The list before the function call')
print(marks)
addBonus(marks) # marks is passed to the function
print('The list after the function call')
print(marks)
Output (id values are illustrative — yours will differ, but the two will be equal):
Reference of list in main 70615968
The list before the function call
[40, 55, 70, 85, 90]
Reference of list inside function 70615968
The list after the function call
[45, 60, 75, 90, 95]
Because passing the list passed a reference, every in-place change made through the parameter name is a change to the caller's list.
Scenario (B): the function ASSIGNS the parameter a new list — changes are NOT reflected back
If, inside the function, the parameter name is assigned a whole new list, then a new list object is created and the parameter becomes a purely local name for it. From that moment the function is working on its own local copy; the caller's list is no longer connected to the parameter, so nothing done afterwards inside the function reaches the calling code.
Watch the ids in this version — the parameter's id is the caller's id before the assignment, and a different id after it:
# Function that assigns its list parameter a brand-new list
def replaceAll(inner):
print('\nID of list inside function before assignment:', id(inner))
inner = [45, 60, 75, 90, 95] # parameter re-assigned a new list
print('ID of list inside function after assignment:', id(inner))
print('The list inside the function after assignment is:')
print(inner)
# end of function
marks = [40, 55, 70, 85, 90] # create a list
print('ID of list before function call:', id(marks))
print('The list before function call:')
print(marks)
replaceAll(marks) # marks passed as parameter
print('\nID of list after function call:', id(marks))
print('The list after the function call:')
print(marks)
Output (again, the exact numbers vary per run):
ID of list before function call: 65565640
The list before function call:
[40, 55, 70, 85, 90]
ID of list inside function before assignment: 65565640
ID of list inside function after assignment: 65565600
The list inside the function after assignment is:
[45, 60, 75, 90, 95]
ID of list after function call: 65565640
The list after the function call:
[40, 55, 70, 85, 90]
``` …