I just stumbled across a problem we all hate: when code works but you don't know why.
There are two classes. A frame, and a stack of frames. First, I create an object of class Frame which I call temporary frame, and add an item to it. Then, I push this frame to an object lf_stack of class Stack. Then, I overwrite the variable tf by creating a new class. The question is: why doesn't this change reflect in the stack? Does python push the address of the object to the stack, meaning that when I assign a new object to the variable "tf", it creates a new object with a new address and the one in the stack remains the same?
EDIT: This behavior is beneficial to me, but I need to understand why it happens
Here is the minimal example:
class Stack:
def __init__(self):
self.content=[]
def push(self,item):
self.content.append(item)
def pop(self):
self.content.pop()
class Frame:
def __init__(self):
self.variables={}
def add_variable(self,name,content):
self.variables[name]=content
def execute_instruction1():
global lf_stack
lf_stack.push(tf)
def execute_instruction2():
global tf
tf=Frame()
lf_stack.push(tf)
def main():
global lf_stack, tf
lf_stack = Stack()
tf = Frame()
tf.add_variable("Foo",4)
#Here, the temporary frame has a variable Foo with value 4
print(tf.variables)
#Here, after adding the temporary frame to a stack, it remains the same
execute_instruction1()
print(tf.variables)
#Here, however, I overwrite the variable "tf" and it changes, but
#I thought it would also change in the stack, but it remains the same
execute_instruction2()
print(tf.variables)
print(lf_stack.content[0].variables)
if __name__ == '__main__':
main()
CodePudding user response:
Every time your code executes tf = Frame()
, python firstly creates a new Frame
object and secondly uses tf
to refer to it so you can keep track of it.
When your code executes: lf_stack.push(tf)
, now both tf
and the internals of lf_stack
are keeping track of the same Frame
object. Objects never know the names of the variables keeping track of them (just the number of variables so they can destroy themselves when this count gets to 0).
However, the next time you execute: tf = Frame()
, as before you get a new Frame
object, but now tf
is reused to keep track of the new Frame
object. If the internals of lf_stack
are keeping track of the previous object, neither are lost.
Also note that there are no deep copies happening here.