为什么在给定默认参数时不同对象中的属性相互连接?
Why are attributes in different objects connected to each other when a default argument is given?
我正在 python 中实现一个基本节点对象。基本上,我实现了一个节点class,属性为f_pointers,并将其设置为默认值[]。每当我尝试更改 f_pointers 的(比方说)node_a 时,我最终会更改 f_pointers of node_b,它们被编程为完全不相关。
我已经通过将默认值更改为 None 并在 __init__ 中设置 forward_pointers 来解决问题。但是,我仍然想知道将来如何避免这个问题,并可能学到一些关于 Python.
的新知识
为了简单起见,我删除了一些不必要的代码部分。
class Node:
def __init__(self, f_pointers = []):
self.f_pointers = f_pointers
def get_pointers(self):
return self.f_pointers
def add_pointers(self, new_pointer):
self.f_pointers.append(new_pointer)
a = Node()
b = Node()
print(a.get_pointers, b.get_pointers)
>>> [] []
a.add_pointers("a")
print(a.get_pointers, b.get_pointers)
>> ["a"] ["a"]
a.add_pointers("b")
print(a.get_pointers, b.get_pointers)
>> ["a","b"] ["a","b"]
可以看出,a和b是完全不相关的对象(除了它们是同一类型的Node),但会相互影响。为什么会这样?
这是因为您引用的是同一个列表(在 __init__
默认参数列表定义中实例化的列表,例如 __init__(self, f_pointers=[])
。发生的情况是,当您在 __init__
中说self.f_points = f_pointers
每次实例化 一个新的 Node
对象时基本上 引用同一个列表的方法代码块。
进一步解释原因here
您要做的是为每个 init 实例化一个新列表,例如:
def __init__(self, f_pointers=None):
self.f_pointers = []
你应该这样做。
class Node:
def __init__(self, f_pointers=None):
if f_pointers:
self.f_pointers = f_pointers
else:
self.f_pointers = []
def get_pointers(self):
return self.f_pointers
def add_pointers(self, new_pointer):
self.f_pointers.append(new_pointer)
a = Node()
b = Node()
print(a.get_pointers(), b.get_pointers())
a.add_pointers("a")
print(a.get_pointers(), b.get_pointers())
你得到这种行为是因为在你的情况下 a.f_pointers
和 b.f_pointers
是同一个列表,它是在你描述你的 class 节点时生成的。
所以 a.f_pointers is b.f_pointers == True
在你的情况下
我正在 python 中实现一个基本节点对象。基本上,我实现了一个节点class,属性为f_pointers,并将其设置为默认值[]。每当我尝试更改 f_pointers 的(比方说)node_a 时,我最终会更改 f_pointers of node_b,它们被编程为完全不相关。
我已经通过将默认值更改为 None 并在 __init__ 中设置 forward_pointers 来解决问题。但是,我仍然想知道将来如何避免这个问题,并可能学到一些关于 Python.
的新知识为了简单起见,我删除了一些不必要的代码部分。
class Node:
def __init__(self, f_pointers = []):
self.f_pointers = f_pointers
def get_pointers(self):
return self.f_pointers
def add_pointers(self, new_pointer):
self.f_pointers.append(new_pointer)
a = Node()
b = Node()
print(a.get_pointers, b.get_pointers)
>>> [] []
a.add_pointers("a")
print(a.get_pointers, b.get_pointers)
>> ["a"] ["a"]
a.add_pointers("b")
print(a.get_pointers, b.get_pointers)
>> ["a","b"] ["a","b"]
可以看出,a和b是完全不相关的对象(除了它们是同一类型的Node),但会相互影响。为什么会这样?
这是因为您引用的是同一个列表(在 __init__
默认参数列表定义中实例化的列表,例如 __init__(self, f_pointers=[])
。发生的情况是,当您在 __init__
中说self.f_points = f_pointers
每次实例化 一个新的 Node
对象时基本上 引用同一个列表的方法代码块。
进一步解释原因here
您要做的是为每个 init 实例化一个新列表,例如:
def __init__(self, f_pointers=None):
self.f_pointers = []
你应该这样做。
class Node:
def __init__(self, f_pointers=None):
if f_pointers:
self.f_pointers = f_pointers
else:
self.f_pointers = []
def get_pointers(self):
return self.f_pointers
def add_pointers(self, new_pointer):
self.f_pointers.append(new_pointer)
a = Node()
b = Node()
print(a.get_pointers(), b.get_pointers())
a.add_pointers("a")
print(a.get_pointers(), b.get_pointers())
你得到这种行为是因为在你的情况下 a.f_pointers
和 b.f_pointers
是同一个列表,它是在你描述你的 class 节点时生成的。
所以 a.f_pointers is b.f_pointers == True
在你的情况下