Anmol Singh Jaggi
Anmol Singh Jaggi

Reputation: 8576

Modifying dictionary inside a function

I have the following code:

def modify_dict(my_dict):
    my_dict = {'b': 2}
    print(my_dict)


def main():
    my_dict = {'a': 1}
    modify_dict(my_dict)
    print(my_dict)

if __name__ == '__main__':
    main()

and it's output is:

{'b': 2}
{'a': 1}

My question is why are the changes done to the dictionary inside the function aren't being reflected in the main() function?
Also, how can I update the dictionary inside the function so that the changes are reflected outside of the function?

Upvotes: 7

Views: 12279

Answers (4)

Pivert
Pivert

Reputation: 785

Just change your function to not reassign it (so no = sign on it), but instead modify it. It works because dictionaries are mutables.

In python, you can update a dict with a dict. So just rewrite your function like this:

def modify_dict(my_dict):
    my_dict.update({'b': 2})
    print(my_dict)

Just got the same problem by using a dictionary to gather output from threads.

Upvotes: 1

NewBee
NewBee

Reputation: 1469

This is an interesting question, I will try to give a shot. My major programming language is Java, but I think CPython&JVM are the same in this case.

In program runtime, it got stack and heap, the stack is used on method call context storage and the heap is for global objects storage.

ok, then, use you code as example

step 1.

my_dict = {'a': 1}

it will create a dict(1) {'a': 1} in heap, and then my_dict is reference to the memory address of the dict(1), it means my_dict now is point to an memory address, but not the {'a': 1} itself.

step 2.

my_dict = modify_dict()

ok, then we call modify_dict function inside main function, the program will put context of main function into a stack(stack1), and the go into function modify_dict with my_dict as argument, now, the program will create a new stack for function modify_dict, and make a copy of arguments, this means my_dict argument now is a reference copy (point to the dict(1) in heap, got the same value as my_dict variable in main, but it's a copy). (indeed, the question has been answer here)

step 3:

my_dict = {'b': 2}

my_dict (a reference point to dict(1) in the heap) now is assign to a new dict(2) in heap, remember my_dict now is not the same with my_dict in main, they are point to two different dict in the heap.

step 4:

program return back to main function, program will pull things from stack, my_dict now is point to dict(1), and dict(1) is not modify in function modify_dict

Sorry for my poor english :)

Upvotes: 2

vmonteco
vmonteco

Reputation: 15413

Just return the new dictionnary and assign this return value to the my_dict in your main() function.

def modify_dict():
    my_dict = {'b': 2}
    print(my_dict)    
    return my_dict

def main():
    my_dict = {'a': 1}
    my_dict = modify_dict()
    print(my_dict)

if __name__ == '__main__':
    main()

The output should be :

{'b': 2}
{'b': 2}

A simpler way would be to direcly return {'b' : 2} without even making a local my_dict variable, like this :

def modify_dict():
    return {'b' : 2}

And this would be basically the same that direcly assign the new value {'b' : 2} to your variable (my_dict = {'b' : 2}), you don't even need a function for that unless if the new value of your dictionnary depends of its previous value.

why isn't the my_dict variable inside main() function modified?

When you pass a variable to a function, the function doesn't use it directly. It only uses a copy of this variable, a new variable that exists only in the function.

So, in a way you have two my_dict variables in your case : - The one inside your modify_dict() function. - And the one inside your main() function.

When editing my_dict in your modify_dict() function, you don't edit the one from the main() function, just a copy of it.

Upvotes: 1

srowland
srowland

Reputation: 1705

The my_dict parameter of modify_dict is a local variable to your function. It contains a reference to your dictionary, but it itself is simply a local variable. If you reach in and modify the dictionary it points to, that would work. For example:

def modify_dict(my_dict):
    my_dict['b'] = 2
    print(my_dict)

Will add to your dictionary. In effect, you are simply assigning a new dictionary to a local variable called my_dict in your function.

As @vmonteco suggests, the best way to achieve this is to simply return the new dictionary from your function and assign the return value.

Upvotes: 4

Related Questions