很抱歉这个笨重的标题,但我不知道如何最好地描述我遇到的问题。
我定义自己的类,然后使用默认构造函数创建对象列表(不传递任何参数)。稍后,当我想访问列表中的一个对象并调用函数方法时,所有列表元素的属性会同时更改为相同的值。看起来列表中的所有元素都是浅层副本。
现在,如果我通过将默认值显式地作为参数传递来创建对象,则列表元素的行为与预期一致,我可以在单个元素上调用该方法而不更改其他元素。
这种行为对我非常困惑和违反直觉,我想理解为什么会这样。
重现行为的最小示例如下所示:
import numpy as np
L = 10.
# define Particle object
class Particle(object):
def __init__(self, position=np.array([0.,0.,0.]) ):
self.position = position
def propagate(self):
x = np.random.exponential(scale=L) # sample mean free path
self.position += np.array([x,0.,0.])
# initialize particle list
particles = 5
particle_list = []
for i in range(0, particles+1):
p = Particle() # <- this does not work as expected!
#p = Particle(np.array([0.,0.,0.])) # <- but this does!
particle_list.append(p)
# testing
print("after creation")
print(particle_list[0].position)
print(particle_list[1].position)
print(particle_list[2].position)
print(particle_list[3].position)
print(particle_list[4].position)
particle_list[2].propagate()
print("after propagation of 1 particle")
print(particle_list[0].position)
print(particle_list[1].position)
print(particle_list[2].position)
print(particle_list[3].position)
print(particle_list[4].position)
这种情况下的输出是
after creation
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
after propagation of 1 particle
[1.19354594 0. 0. ]
[1.19354594 0. 0. ]
[1.19354594 0. 0. ]
[1.19354594 0. 0. ]
[1.19354594 0. 0. ]
即使只在一个元素上调用该方法。相反,如果我将Particle()
更改为Particle(np.array([0.,0.,0.]))
,则输出变为
after creation
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
after propagation of 1 particle
[0. 0. 0.]
[0. 0. 0.]
[7.55848724 0. 0. ]
[0. 0. 0.]
[0. 0. 0.]
这就是我想要的。现在我可以务实,只是接受这个语言的怪癖,但如果一个对象没有我可以传递给构造函数的参数,我该怎么办?
PS:我使用的是Python 3.6.4