我试图在同一个类中创建一个类的新对象,但是它不是创建一个全新的对象,而是创建一个对我当前使用的同一个对象的新引用。你知道吗
因此,如果我改变一个对象的值,它也会改变另一个对象的值——尽管我可能应该有两个完全不同的对象。你知道吗
使用copy.deepcopy()
方法修复了引用的问题,但我猜它的工作方式也应该有所不同。你知道吗
我的代码在这个特定的实现中是如何工作的?它是否有理由创建同一对象的浅层副本,即使代码可能应该创建它的新实例?你知道吗
这是一个稍微简化的代码段:
class Vec4():
def __init__(self, x = 0, y = 0, z = 0, w = 0):
self.values = [x,y,z,w]
def __str__(self):
return str(self.values[0]) + ' ' + str(self.values[1]) + ' ' + str(self.values[2]) + ' ' + str(self.values[3])
def setValue(self, index, value):
self.values[index] = value
def scalar(self, vector):
"""returns the result of the scalar multiplication"""
result = 0
for u in range(4):
result += self.values[u] * vector.values[u]
return result
class Matrix4():
def __init__(self, row1 = Vec4(), row2 = Vec4(), row3 = Vec4(), row4 = Vec4()):
self.m_values = [row1,row2,row3,row4]
self.trans_values = [Vec4(),Vec4(),Vec4(),Vec4()]
self.set_transp_matrix()
def __str__(self):
return self.m_values[0].__str__() + '\n' + self.m_values[1].__str__() + '\n' + self.m_values[2].__str__() + '\n' + self.m_values[3].__str__()
def setIdentity(self):
identity = Matrix4(Vec4(1,0,0,0),
Vec4(0,1,0,0),
Vec4(0,0,1,0),
Vec4(0,0,0,1))
for i in range(4):
for j in range(4):
self.m_values[i].values[j] = identity.m_values[i].values[j]
def set_transp_matrix(self):
for t in range(4):
for s in range(4):
self.trans_values[t].values[s] = self.m_values[s].values[t]
def get_trans_matrix(self):
return self.trans_values[0].__str__() + '\n' + self.trans_values[1].__str__() + '\n' + self.trans_values[2].__str__() + '\n' + self.trans_values[3].__str__()
def mulM(self, m):
print(self, "\n")
matrixResult = Matrix4()
print(matrixResult, "\n")
for row in range(4): # rows of self
for element in range(4):
value = self.m_values[row].scalar(m.trans_values[element])
matrixResult.m_values[row].setValue(element, value)
return matrixResult
class ScaleMatrix(Matrix4):
def __init__(self, m_scale = Vec4(1,1,1), *args, **kwargs):
super(ScaleMatrix, self).__init__(*args, **kwargs)
self.m_scale = m_scale
self.update()
def getScale(self):
"""Returns the scale vector, only x, y and z are relevant"""
return self.m_scale
def setScale(self, v):
"""Sets the scale vector, only x, y and z are relevant"""
self.m_scale = v
self.update()
def update(self):
"""Calculates the scale matrix"""
self.setIdentity()
for i in range(3):
self.m_values[i].values[i] = self.getScale().values[i]
return self
if __name__ == "__main__":
#Simple Constructor and Print
a = Vec4(1,2,3,4)
b = Vec4(5,6,7,8)
c = Vec4(9,10,11,12)
d = Vec4(13,14,15,16)
A = Matrix4(a, b, c, d)
D = ScaleMatrix()
D.setScale(Vec4(3, 4, 5, 1))
print(D.mulM(A))
问题在于类Matrix4
,方法mulM()
,其中matrixResult = Matrix4()
应该创建一个全新的Matrix4()
实例(其中Vec4()
的所有值都应该是0
),而不是简单地复制self
对象。print
的输出显示如下:
3 0 0 0
0 4 0 0
0 0 5 0
0 0 0 1
3 0 0 0
0 4 0 0
0 0 5 0
0 0 0 1
3 6 51 672
20 64 508 6688
45 140 1170 15340
13 40 334 4396
所以第二个矩阵不应该等于第一个矩阵。
但是,如果我创建一个普通的Matrix4()
对象,而不是在上述代码片段的最后扩展Matrix4()
的ScaleMatrix()
对象,则不会出现问题。你知道吗
Python v.3.6.4版
查看Python constructor and default value和"Least Astonishment" and the Mutable Default Argument您的问题与上面链接的问题中描述的问题基本相似。你知道吗
另外,在声明类时,使其成为
object
的子类:最后,要解决您的特定问题,请删除初始值设定项的默认值。例如,执行以下操作:
默认的
ScaleMatrix
参数m_scale
也是如此:Python在定义函数时计算默认参数。定义时:
创建一个
Vec4
实例,现在每次调用这个__init__
方法时,这个实例都将用作默认值。你知道吗第一次创建
Matrix4
实例时,将执行__init__
,并通过名称row1
引用该实例那么你有:
所以这个实例现在由self.m\u值[0]引用。你知道吗
稍后,在
ScaleMatrix.update
中,更新这个Vec4
实例:下次不带参数调用
Matrix4.__init__
时,将使用默认值,这是刚刚更新的Vec4
。你知道吗当使用空列表作为默认参数时,也有类似的行为,请参见“Least Astonishment” and the Mutable Default Argument 。你知道吗
避免此问题的通常方法是避免使用可变对象作为默认参数。你可以做:
作为输出:
相关问题 更多 >
编程相关推荐