Question:
There is a function:
def foo(...):
my_dict = {
...
}
...
I always thought that each time such a function is called, the my_dict
dictionary will be re-created each time. But when checking, it turned out that id(my_dict)
the same from call to call. At the same time, even if you change the dictionary inside the function, the dictionary remains the same when the function is called again, but its id
still does not change.
Accordingly, the questions are:
Is a dictionary created every time the function is called?
How is it that an object has the same id
, but does not accumulate changes on new function calls?
def foo(x):
a = {1: 2, 4:5}
a[x] = x**2
print(id(a), a)
if __name__ == "__main__":
for i in range(5):
foo(i)
2581778427192 {1: 2, 4: 5, 0: 0}
2581778427192 {1: 1, 4: 5}
2581778427192 {1: 2, 4: 5, 2: 4}
2581778427192 {1: 2, 4: 5, 3: 9}
2581778427192 {1: 2, 4: 16}
Answer:
According to the documentation https://docs.python.org/3/library/functions.html#id , objects that do not overlap can have the same id name. It turns out that upon exiting the function, the dictionary is deleted, its id becomes vacant and is issued for the same dictionary, but at the next function call. The following code confirms this theory. The same id will be issued under the dictionary and into another function.
def boo(x):
b = {'p': 1, 'q': 0}
print(id(b))
def foo(x):
a = {1: 2, 4:5}
print(id(a), a)
return a
if __name__ == "__main__":
foo(0)
foo(1)
boo(0)
foo(2)
>>>
1899014090040 {1: 2, 4: 5}
1899014090040 {1: 2, 4: 5}
1899014090040
1899014090040 {1: 2, 4: 5}
In turn, if we cross the lifetime of these dictionaries, then everything falls into place, new id dictionaries are issued:
if __name__ == "__main__":
a1 = foo(0)
a2 = foo(1)
boo(0)
a3 = foo(2)
a4 = foo(3)
>>>
2388301606200 {1: 2, 4: 5}
2388301606632 {1: 2, 4: 5}
2388301606272
2388301606272 {1: 2, 4: 5}
2388332816064 {1: 2, 4: 5}
Well, a small check that new dictionaries are created:
COUNTER = 0
class Fake:
def __init__(self):
global COUNTER
COUNTER += 1
print("A new version of me has been created. Counter = ", COUNTER)
def __repr__(self):
return str(COUNTER)
def foo(x):
a = {1: 2, 4:Fake()}
if __name__ == "__main__":
foo(0)
foo(1)
foo(2)
>>>
A new version of me has been created. Counter = 1
A new version of me has been created. Counter = 2
A new version of me has been created. Counter = 3