Reputation: 410
I'm relatively new to Python. I was working in a project to create objects Square and Points. A Square is composed of 4 points which are the upper left corner, upper right corner and so on.
Now in my main function I create 4 point objects and I send them to the constructor of Square class, it creates my Square.
When I do the same for another Square with different values for the point objects, the values for my previously created Square are overwritten, so at the end I have two same objects. Do you know why this is happening?
This is my code:
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()
Any kind of help will be highly appreciated ;)
Cheers!
Upvotes: 1
Views: 706
Reputation: 12077
It's happening because you've defined the four corner variables in the Square
class as class variables. This means that they are shared between all instances of that class.
Here's a cleaner version of your Square
class. There are instance variables self.ul, self.ll
and so forth. You don't need to specify a Point
instance for these in the __init__
because you're already doing that in the main function where you pass them as arguments.
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 makes a good point about passing points as arguments, as if you pass the same point object to two squares and modify it, any changes you make will reflect in both squares.
You can get around this by passing corner values to the __init__
instead of Point
objects, and then create the instances in the __init
__
Here's a complete example:
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))
I'd also advice you to use more readable variable names. You save nothing by shortening upper_right
to ur
. On the contrary, when you return to this code in a year, you'll curse at yourself.
Upvotes: 5