构造函数覆盖已创建对象的先前值
我对Python还比较陌生。最近我在做一个项目,想创建两个对象:正方形(Square)和点(Points)。一个正方形是由四个点组成的,分别是左上角、右上角等等。
在我的主函数中,我创建了四个点对象,然后把它们传给正方形类的构造函数,这样就生成了我的正方形。
但是,当我用不同的点对象值再创建一个正方形时,之前创建的正方形的值被覆盖了,最后我得到的两个正方形是一样的。你知道这是为什么吗?
这是我的代码:
class Point(object):
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
class Square(object):
ul = Point()
ll = Point()
ur = Point()
lr = Point()
def __init__(self, ul, ll, ur, lr):
self.ul.x = ul.x
self.ll.x = ll.x
self.ur.x = ur.x
self.lr.x = lr.x
self.ul.y = ul.y
self.ll.y = ll.y
self.ur.y = ur.y
self.lr.y = lr.y
def main():
ul1 = Point(1, 2)
ll1 = Point(1, 1)
ur1 = Point(2, 2)
lr1 = Point(2, 1)
s1 = Square(ul1, ll1, ur1, lr1)
ul2 = Point(3, 3)
ll2 = Point(3, 2)
ur2 = Point(4, 3)
lr2 = Point(4, 2)
s2 = Square(ul2, ll2, ur2, lr2)
#At this point s1 and s2 have the same values...
if __name__ == '__main__':
main()
任何帮助我都会非常感激;)
谢谢!
1 个回答
5
这个问题发生的原因是你在 Square
类中把四个角的变量定义成了类变量。这意味着这些变量在这个类的所有实例之间是共享的。
下面是你 Square
类的一个更清晰的版本。这里使用了实例变量 self.ul, self.ll
等等。你在 __init__
方法中不需要为这些指定一个 Point
实例,因为你已经在主函数中把它们作为参数传入了。
class Square(object):
def __init__(self, ul, ll, ur, lr):
self.ul = ul
self.ll = ll
self.ur = ur
self.lr = lr
def main():
s1 = Square(Point(1, 2), Point(1, 1), Point(2, 2), Point(2, 1))
s2 = Square(Point(3, 3), Point(3, 2), Point(4, 3), Point(4, 2))
print s1.ul.x # 1
print s1.lr.y # 2
HyperBoreus 提到的一个好点子是把点作为参数传递。如果你把同一个点对象传给两个正方形并修改它,那么你所做的任何更改都会在两个正方形中反映出来。
你可以通过把角的值传给 __init__
方法,而不是 Point
对象,来解决这个问题,然后在 __init__
方法中创建实例。
下面是一个完整的例子:
class Point(object):
def __init__(self, x = 0, y = 0):
self.x = x
self.y = y
class Square(object):
def __init__(self, ul, ll, ur, lr):
self.ul = Point(ul[0], ul[1])
self.ll = Point(ll[0], ll[1])
self.ur = Point(ur[0], ur[1])
self.lr = Point(lr[0], lr[1])
def main():
square_one = Square((1, 2), (1, 1), (2, 2), (2, 1))
square_two = Square((3, 3), (3, 2), (4, 3), (4, 2))
我还建议你使用更易读的变量名。把 upper_right
简化成 ur
并没有什么好处。相反,当你一年后再回来看这段代码时,你会对自己感到很懊恼。