2

I was looking over my review paper and didn't understand the following coding.

def function_b(b_list, high_num):
    c_list = [0, 0, 0, 0, 0, 0,0]
    i = 0
    for num in b_list:
        if num > high_num:
            c_list[i] = num
        i = i + 1
    b_list = c_list

def main():
    b_list = [1,3, 6, 4, 1, 2, 8]
    high_num = 4
    function_b(b_list, high_num)
    print(b_list)

main()

the result was [1, 3, 6, 4, 1, 2, 8] Why did;t the b_list get updated with c_list?

swag2198
  • 2,546
  • 1
  • 7
  • 18
Enoch Kim
  • 21
  • 3
  • The variable `b_list` in main is a completely different variable that the one in `function_b`. When you call function_b, one b_list ends up pointing to the value that the other one had been pointing to. But then you assign b_list to a completely different value, and this link is broken. – Frank Yellin Nov 05 '20 at 06:58

3 Answers3

1

As this answer explains:

If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart's delight, but if you rebind the reference in the method, the outer scope will know nothing about it, and after you're done, the outer reference will still point at the original object.

In other words, the line b_list = c_list only changes what b_list points to in the function. It doesn't change what b_list points to in main. So the solution is to modify the elements of b_list, rather than pointing b_list to a whole new list.

Another tip comes from this question. If you need both the index into the array, and the value at that index, you can use the enumerate function.

Putting it all together, the function could be written like this:

def function_b(b_list, high_num):
    for i, num in enumerate(b_list):  # use 'enumerate' to get both index and value
        if num <= high_num:           # check for small numbers in the list
            b_list[i] = 0             # change the small numbers to 0
user3386109
  • 34,287
  • 7
  • 49
  • 68
0

This is because inside function_b, b_list is just a reference that is being re-assigned. The actual list is not being modified.

A good solution would say return c_list towards the end of the function_b(..). main() can then say b_list = function_b(b_list, high_num)`.

In your particular case, you can do the following to get what you're looking for (although personally I tend to avoid doing this):

b_list[:] = c_list  # Modified the actual contents of the list
                    # that b_list points at, instead of just
                    # making the local b_list point to whatever c_list
                    # is pointing at.
UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
0

python function parameters are passed by reference and so it does not make a copy of the object when it gets passed in. The object can either be mutable(list) or immutable (str). You can perform work on the object the parameter points to but you can't really bind parameter to something else.

def function_b(b_list, high_num):
  b_list = [] # this has no effect
  b_list.append(10) # but you can modify it 

While you can modify the function parameter since it s a list, the safest way is to rebind b_list in main() as a return value of the function_b mentioned in previous posts.

uhmas
  • 68
  • 1
  • 6