This is my very first question to StackOverflow. If the format of this question is not standard, please feel free to let me know.
I have been transiting from Matlab to Python after I found out about iPython. I use VSCode and Jupyter interface along with "# %%" header in order to get the interactive console. So far, I love everything and I feel like full transition is needed for my work.
I have been having some mysterious issue with initialising class instance.
Suppose we have two minimal files that recreate the issue:
main.py
# %%
%reset -f
from dummy import Dummy
dummy = Dummy()
print('created = %s' % dummy.others)
dummy.receive('something')
print('received = %s' % dummy.others)
dummy.py
class Dummy():
def __init__(self, others=[]):
self._others = others
pass
def receive(self, value):
self._others.append(value)
@property
def others(self):
return self._others
When I run main.py for the first time after restarting the Jupyter kernel, I get
created = []
received = ['something']
which is totally expected. But, if I run it again, I get
created = ['something']
received = ['something', 'something']
indicating that "dummy" variable is not initialised as it should.
In order to track down the source, I changed the scripts so that
main.py (debugging)
# %%
%reset -f
from dummy import Dummy
try:
print(dummy.others)
except:
print('dummy not found')
dummy = Dummy()
print('created = %s' % dummy.others)
dummy.receive('something')
print('received = %s' % dummy.others)
dummy.py (debugging)
class Dummy():
def __init__(self, others=[]):
print('input = %s' % others)
self._others = others
print('internal = %s' % self._others)
pass
def receive(self, value):
self._others.append(value)
@property
def others(self):
return self._others
When I run the main script after restarting the kernel, I get
dummy not found
input = []
internal = []
created = []
received = ['something']
and the below after another run
dummy not found
input = ['something']
internal = ['something']
created = ['something']
received = ['something', 'something']
It is so clear that "dummy" variable is successfully deleted after "%reset -f", but somehow input argument "others" in Dummy constructor is assigned to the previously assigned, rather than "[]".
But why?
When I change "def receive(self, value)" in dummy.py as follows, I don't have the problem anymore:
def receive(self, value):
self._others = self._others + [value]
But again, this change is to with mutability if I understand correctly. It should affect the input argument assignment in the constructor.
Also, this issue doesn't appear when Dummy class is in the same file (main.py)
Could you please let me know what I am missing?
Edit: I now understand that I should be careful with mutable init parameters. But my other fundamental question is why "%reset -f" in iPython did not clear everything. It did delete dummy variable, but the init parameter "others" was mysteriously assigned to the previous. Isn't the magic thingy supposed to delete everything?