Variable scope - "global x" didn't work... - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Variable scope - "global x" didn't work... (/thread-31639.html) |
Variable scope - "global x" didn't work... - ptrivino - Dec-24-2020 I am struggling to understand updating a 'global' dictionary (i.e., it's defined in the main module and I want to update it in a subroutine). I understand that I need to do something since dict_1 in the mainline isn't what would be updated in a function. So I tried this experiment: dict_1 = {} dict_2 = {} def upd_dict1(dict_1_copy): print("sub dict_1_copy a is " + str(dict_1_copy["a"])) dict_1_copy["a"] = 100 print("sub dict_1_copy a is " + str(dict_1_copy["a"])) return dict_1_copy if __name__ == "__main__": dict_1["a"] = 1 dict_1["b"] = 2 dict_2["a"] = 0 dict_2["b"] = 22 print("dict_1 a is " + str(dict_1["a"]) + " b4 upd - sb 1") print("dict_1 b is " + str(dict_1["b"]) + " b4 upd - sb 2") print("dict_2 a is " + str(dict_2["a"]) + " b4 upd - sb 0") print("dict_2 b is " + str(dict_2["b"]) + " b4 upd - sb 22\n") dict_2 = upd_dict1(dict_1) print("dict_1 a is " + str(dict_1["a"]) + " aft upd - sb 1") print("dict_1 b is " + str(dict_1["b"]) + " aft upd - sb 2") print("dict_2 a is " + str(dict_2["a"]) + " aft upd - sb 100") print("dict_2 b is " + str(dict_2["b"]) + " aft upd - sb 2\n") dict_1 = dict_2 print("dict_1 a is " + str(dict_1["a"]) + " aft copy - sb 100") print("dict_1 b is " + str(dict_1["b"]) + " aft copy - sb 2") print("dict_2 a is " + str(dict_2["a"]) + " aft copy - sb 100") print("dict_2 b is " + str(dict_2["b"]) + " aft copy - sb 2")Which *should* give the results shown as "sb X" in the print statements. But what I get is I completely do not understand why the line marked THIS get what it gets.Can anyone tell me what I'm missing here? Paul RE: Variable scope - "global x" didn't work... - bowlofred - Dec-24-2020 You call it a copy, but there are no copies made anywhere. When you pass an object to a function, if that object is mutable the function can modify it. Here you pass dict1 to upd_dict1 on line 19. This function both modifies the object that is passed in, and returns another reference to that object. Before line 19 you have two dictionaries: dict_1 and dict_2. After line 19, both variables point at the same object (the original dict_2 is discarded). Line 24 doesn't do anything because they are already the same. You can add a statement like: print(f"dict_1 and dict_2 are the same object: {dict_1 is dict_2}" RE: Variable scope - "global x" didn't work... - deanhystad - Dec-24-2020 Normally you do not need to use "global" with dictionaries and lists. "global" controls how assignment is done. In the code below the "global x" in set_global_x() tells Python that the assignment "x = value" should not create a new x variable in the function scope. The same assignment in set_local_x() creates "x" inside the set_local_x namespace. Setting this x does not change the value of the "global" x. x = 1 def set_global_x(value): global x x = value def set_local_x(value): x = value def print_x(): print('x =', x) print_x() set_global_x(2) print_x() set_local_x(3) print_x() When using a mutable object like a dictionary or list you don't need to use global if all you want to do is change something in the mutable object.x = [1] def set_global_x(value): global x x[0] = value def set_local_x(value): x[0] = value def print_x(): print('x =', x[0]) print_x() set_global_x(2) print_x() set_local_x(3) print_x()
RE: Variable scope - "global x" didn't work... - ptrivino - Dec-25-2020 (Dec-24-2020, 08:13 PM)bowlofred Wrote: You call it a copy, but there are no copies made anywhere. When you pass an object to a function, if that object is mutable the function can modify it. Thank you. The thing I am trying to fix is that when I do this in a third-level function: for curr_id in dict_1: # loop through the dictionary # code code code dict_1[curr_id].incl_ips.append(ipaddress.ip_network(rng_chop[0] + "/" + str(myprefix), False)) # code code codeit appends the value in the loop iteration to THE SAME dictionary entry. Also, from my OP, essentially dict_1_copy is discarded when I exit the function and recreated the next time the function is called? RE: Variable scope - "global x" didn't work... - bowlofred - Dec-25-2020 (Dec-25-2020, 12:00 AM)ptrivino Wrote: Thank you. The thing I am trying to fix is that when I do this in a third-level function: I'm not sure I follow this part. What are you expecting it to append to? Quote:Also, from my OP, essentially dict_1_copy is discarded when I exit the function and recreated the next time the function is called? Yes. I wouldn't use "discarded" here because the actual data remains (since it has another name outside the function). I would say it is "reassigned" the next time the function is called. No data is created at that time. RE: Variable scope - "global x" didn't work... - ptrivino - Dec-28-2020 (Dec-25-2020, 12:44 AM)bowlofred Wrote:(Dec-25-2020, 12:00 AM)ptrivino Wrote: Thank you. The thing I am trying to fix is that when I do this in a third-level function: In the dict_1 entries I set the value to an object/class with 4 attributes (incl_ips is one of them), each a list of other values. But what doesn't work is that, in each loop through with a new curr_id, the SAME dictionary entry (or possibly ALL entries, I've seen that in another try)is updated/appended to. |