iPython 中神秘分配的构造函数参数
Mysteriously assigned constructor argument in iPython
这是我向 Whosebug 提出的第一个问题。如果这个问题的格式不规范,请随时告诉我。
在发现 iPython 之后,我一直在从 Matlab 过渡到 Python。我使用 VSCode 和 Jupyter 界面以及“# %%” header 以获得交互式控制台。到目前为止,我喜欢一切,我觉得我的工作需要完全过渡。
我在初始化 class 实例时遇到了一些神秘的问题。
假设我们有两个重现问题的最小文件:
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
当我 运行 main.py 第一次重启 Jupyter 内核后,我得到
created = []
received = ['something']
这完全在意料之中。但是,如果我再次 运行 它,我会得到
created = ['something']
received = ['something', 'something']
表示“虚拟”变量未按应有的方式初始化。
为了追根溯源,我修改了脚本,这样
main.py(调试中)
# %%
%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(调试中)
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
当我运行主脚本重启内核后,我得到
dummy not found
input = []
internal = []
created = []
received = ['something']
和下面一个接一个运行
dummy not found
input = ['something']
internal = ['something']
created = ['something']
received = ['something', 'something']
很明显,在“%reset -f”之后成功删除了“dummy”变量,但是不知何故,Dummy构造函数中的输入参数“others”被分配给了之前分配的,而不是“[]”。
但是为什么呢?
当我如下更改 dummy.py 中的“def receive(self, value)”时,问题不再存在:
def receive(self, value):
self._others = self._others + [value]
但是,如果我理解正确的话,这个变化是可变的。它应该会影响构造函数中的输入参数赋值。
此外,当 Dummy class 在同一个文件 (main.py)
中时,不会出现此问题
你能告诉我我缺少什么吗?
编辑:
我现在明白我应该小心可变的初始化参数。但我的另一个基本问题是为什么 iPython 中的“%reset -f”没有清除所有内容。它确实删除了虚拟变量,但初始化参数“其他”神秘地分配给了前一个。魔法不是应该删除所有内容吗?
这是一个正确的 dummy.py
脚本,没有将可变参数作为默认值:
class Dummy():
def __init__(self, others=None):
self._others = others or []
pass
def receive(self, value):
self._others.append(value)
@property
def others(self):
return self._others
输出:
created = []
received = ['something']
这是我向 Whosebug 提出的第一个问题。如果这个问题的格式不规范,请随时告诉我。
在发现 iPython 之后,我一直在从 Matlab 过渡到 Python。我使用 VSCode 和 Jupyter 界面以及“# %%” header 以获得交互式控制台。到目前为止,我喜欢一切,我觉得我的工作需要完全过渡。
我在初始化 class 实例时遇到了一些神秘的问题。
假设我们有两个重现问题的最小文件:
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
当我 运行 main.py 第一次重启 Jupyter 内核后,我得到
created = []
received = ['something']
这完全在意料之中。但是,如果我再次 运行 它,我会得到
created = ['something']
received = ['something', 'something']
表示“虚拟”变量未按应有的方式初始化。
为了追根溯源,我修改了脚本,这样
main.py(调试中)
# %%
%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(调试中)
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
当我运行主脚本重启内核后,我得到
dummy not found
input = []
internal = []
created = []
received = ['something']
和下面一个接一个运行
dummy not found
input = ['something']
internal = ['something']
created = ['something']
received = ['something', 'something']
很明显,在“%reset -f”之后成功删除了“dummy”变量,但是不知何故,Dummy构造函数中的输入参数“others”被分配给了之前分配的,而不是“[]”。
但是为什么呢?
当我如下更改 dummy.py 中的“def receive(self, value)”时,问题不再存在:
def receive(self, value):
self._others = self._others + [value]
但是,如果我理解正确的话,这个变化是可变的。它应该会影响构造函数中的输入参数赋值。
此外,当 Dummy class 在同一个文件 (main.py)
中时,不会出现此问题你能告诉我我缺少什么吗?
编辑: 我现在明白我应该小心可变的初始化参数。但我的另一个基本问题是为什么 iPython 中的“%reset -f”没有清除所有内容。它确实删除了虚拟变量,但初始化参数“其他”神秘地分配给了前一个。魔法不是应该删除所有内容吗?
这是一个正确的 dummy.py
脚本,没有将可变参数作为默认值:
class Dummy():
def __init__(self, others=None):
self._others = others or []
pass
def receive(self, value):
self._others.append(value)
@property
def others(self):
return self._others
输出:
created = []
received = ['something']