为什么实例变量在这段代码中引用同一个对象?
Why Instance variables reference the same object in this code?
我想在has-a关系中实现Shapeclass中的move方法(所以Shapeclass不继承CPointclass),但是在设置class变量。
给定的代码是:
class CPoint:
def __init__(self, x = 0, y = 0):
self.__x = x
self.__y = y
def __str__(self):
return f"pos({self.__x},{self.__y})"
def get_x(self):
return self.__x
def set_x(self, new_x):
self.__x = new_x
def get_y(self):
return self.__y
def set_y(self, new_y):
self.__y = new_y
def move(self, a, b):
self.__x += a
self.__y += b
return CPoint(self.__x,self.__y)
class Shape:
def __init__(self, color = "yellow", filled = True, pos = CPoint()):
#So each pos must reference the different CPoint() instance
self.__color = color
self.__filled = filled
self.__pos = pos
def __str__(self):
return f"{self.__pos}({self.__color},{self.__filled})"
def move(self, a, b):
self.__pos.move(a,b)
if type(self) == Shape:
return f"{self}"
else:
return f"{self.__pos}{self}"
def main():
a = Shape()
b = Shape("red")
a.move(2,3)
print(b.move(4,5))
main()
结果是:
pos(0,0)(yellow,True)
pos(0,0)(red,True)
pos(2,3)(yellow,True)
pos(6,8)(red,True)
结果应该是这样的:
pos(0,0)(yellow,True)
pos(0,0)(red,True)
pos(2,3)(yellow,True)
pos(4,5)(red,True)
并且我在python导师上执行了代码,代码的可视化是这样的:
python tutor visualization
所以 Shape() 和 Shape("red") 对象应该引用不同的 CPoint 实例(因为它们有自己的位置数据),但它们引用相同的实例,即使我设置了默认参数 'pos = CPoint()'.
谁能解释一下为什么他们引用同一个实例,以及如何解决这个问题?
这就是 python 参数默认值的方式,默认参数在函数声明期间初始化一次,而不是每次调用函数时都像您使用其他语言如 Javascript https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
因此,同一个 CPoint()
实例在不同的构造函数调用之间共享。
要避免这种行为,您可以尝试在函数本身内进行设置。
class Shape:
def __init__(self, color = "yellow", filled = True, pos = None):
if pos is None:
pos = CPoint()
#So each pos must reference the different CPoint() instance
self.__color = color
self.__filled = filled
self.__pos = pos
我想在has-a关系中实现Shapeclass中的move方法(所以Shapeclass不继承CPointclass),但是在设置class变量。
给定的代码是:
class CPoint:
def __init__(self, x = 0, y = 0):
self.__x = x
self.__y = y
def __str__(self):
return f"pos({self.__x},{self.__y})"
def get_x(self):
return self.__x
def set_x(self, new_x):
self.__x = new_x
def get_y(self):
return self.__y
def set_y(self, new_y):
self.__y = new_y
def move(self, a, b):
self.__x += a
self.__y += b
return CPoint(self.__x,self.__y)
class Shape:
def __init__(self, color = "yellow", filled = True, pos = CPoint()):
#So each pos must reference the different CPoint() instance
self.__color = color
self.__filled = filled
self.__pos = pos
def __str__(self):
return f"{self.__pos}({self.__color},{self.__filled})"
def move(self, a, b):
self.__pos.move(a,b)
if type(self) == Shape:
return f"{self}"
else:
return f"{self.__pos}{self}"
def main():
a = Shape()
b = Shape("red")
a.move(2,3)
print(b.move(4,5))
main()
结果是:
pos(0,0)(yellow,True)
pos(0,0)(red,True)
pos(2,3)(yellow,True)
pos(6,8)(red,True)
结果应该是这样的:
pos(0,0)(yellow,True)
pos(0,0)(red,True)
pos(2,3)(yellow,True)
pos(4,5)(red,True)
并且我在python导师上执行了代码,代码的可视化是这样的: python tutor visualization
所以 Shape() 和 Shape("red") 对象应该引用不同的 CPoint 实例(因为它们有自己的位置数据),但它们引用相同的实例,即使我设置了默认参数 'pos = CPoint()'.
谁能解释一下为什么他们引用同一个实例,以及如何解决这个问题?
这就是 python 参数默认值的方式,默认参数在函数声明期间初始化一次,而不是每次调用函数时都像您使用其他语言如 Javascript https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
因此,同一个 CPoint()
实例在不同的构造函数调用之间共享。
要避免这种行为,您可以尝试在函数本身内进行设置。
class Shape:
def __init__(self, color = "yellow", filled = True, pos = None):
if pos is None:
pos = CPoint()
#So each pos must reference the different CPoint() instance
self.__color = color
self.__filled = filled
self.__pos = pos