ID of object not being saved - python

I have the following class which I made:
import math
class Point:
"""Two-Dimensional Point(x, y)"""
def __init__(self, x=0, y=0):
# Initialize the Point instance
self.x = x
self.y = y
def __iter__(self):
yield self.x
yield self.y
def __add__(self, other):
addedx = self.x + other.x
addedy = self.y + other.y
return Point(addedx, addedy)
def __mul__(self, other):
mulx = self.x * other
muly = self.y * other
return Point(mulx, muly)
def __rmul__(self, other):
mulx = self.x * other
muly = self.y * other
return Point(mulx, muly)
#classmethod
def from_tuple(cls, tup):
x, y = tup
return cls(x, y)
def loc_from_tuple(self, tup):
self.x, self.y = tup
#property
def magnitude(self):
# """Return the magnitude of vector from (0,0) to self."""
return math.sqrt(self.x ** 2 + self.y ** 2)
def distance(self, self2):
return math.sqrt((self2.x - self.x) ** 2 + (self2.y - self.y) ** 2)
def __str__(self):
return 'Point at ({}, {})'.format(self.x, self.y)
def __repr__(self):
return "Point(x={},y={})".format(self.x, self.y)
I don't exactly know how to explain it but I basically want to be able to maintain a points id despite mathematical operations. For example:
point1 = Point(2, 3)
point2 = Point(4, 5)
id1 = id(point1)
point1 += point2
print(point1)
Point(x=6, y=8)
print(id1 == id(point1))
True
print(point2)
Point(x=4, y=5)
Is there a reason this doesn't happen in my code. It says False during the id part in mine.

The id is basically the memory address. If you make a new object, it will probably have a different id. If you want a mutable Point object for some reason consider the __iadd__ (and friends) methods instead, which can do the update in-place.

Related

How to add a #classmethod to a class that allows circle objects to be created with a tuple instead of a point for a center’s location

I have the below code which is are point and circle classes:
import math
class Point:
"""Two-Dimensional Point(x, y)"""
def __init__(self, x=0, y=0):
# Initialize the Point instance
self.x = x
self.y = y
def __iter__(self):
yield self.x
yield self.y
def __iadd__(self, other):
self.x = self.x + other.x
self.y = self.y + other.y
return self
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
def __mul__(self, other):
mulx = self.x * other
muly = self.y * other
return Point(mulx, muly)
def __rmul__(self, other):
mulx = self.x * other
muly = self.y * other
return Point(mulx, muly)
#classmethod
def from_tuple(cls, tup):
x, y = tup
return cls(x, y)
def loc_from_tuple(self, tup):
# self.x=t[0]
# self.y=t[1]
self.x, self.y = tup
#property
def magnitude(self):
# """Return the magnitude of vector from (0,0) to self."""
return math.sqrt(self.x ** 2 + self.y ** 2)
def distance(self, self2):
return math.sqrt((self2.x - self.x) ** 2 + (self2.y - self.y) ** 2)
def __str__(self):
return 'Point at ({}, {})'.format(self.x, self.y)
def __repr__(self):
return "Point(x={},y={})".format(self.x, self.y)
class Circle():
"""Circle(center, radius) where center is a Point instance"""
def __init__(self, center= Point(0,0), radius=1):
# Point.__init__(self,center)
self.center = 1 * center
self.radius = radius
# if not isinstance(center,Point):
# raise TypeError("The center must be a Point!")
#property
def center(self):
return self._center
#center.setter
def center(self, _center):
self._center = _center
if (isinstance(self._center, Point) is False):
raise TypeError("The center must be a Point!")
def __getitem__(self,item):
return self.center[item]
def __iadd__(self, other):
self.center.x = self.center.x + other.center.x
self.center.y = self.center.y + other.center.y
self.radius = self.radius + other.radius
self = Circle(Point(self.center.x, self.center.y), self.radius)
return self
def __add__(self,other):
return Circle(
Point(self.center.x + other.center.x, self.center.y+other.center.y),
self.radius + other.radius)
#classmethod
def from_tuple(cls, center,radius):
return cls(center, radius)
#property
def radius(self):
return self._radius
#radius.setter
def radius(self, radius):
if radius < 0:
raise ValueError('The radius cannot be negative')
self._radius = radius
#property
def area(self):
"""Calculate and return the area of the Circle"""
return math.pi * self.radius ** 2
#property
def diameter(self):
"""Calculate and return the diameter of the Circle"""
return self.radius * 2
def __str__(self):
return "Circle with center at ({0}, {1}) and radius {2}".format(self.center.x, self.center.y, self.radius)
def __repr__(self):
return "Circle(center=Point({0}, {1}), radius={2})".format(self.center[0],self.center[1],self.radius)
I added a #classmethod called from_tuple() to the Circle class that allows Circle objects to be created with a tuple instead of a Point for the center’s location. The resultant instance should have a Point as the center just like any other Circle object. I am supposed to code it so the tuple input is required, but allow the radius to default to 1. The expected output is below:
center_point = 3, 4
circle = Circle.from_tuple(center=center_point)
print(circle)
Circle(center=Point(3, 4), radius=1)
circle = Circle.from_tuple(center=center_point, radius = 3)
print(circle)
Circle(center=Point(3, 4), radius=3)
circle = Circle.from_tuple(center_point, 2)
print(circle)
Circle(center=Point(3, 4), radius=2)
circle = Circle.from_tuple()
Traceback (most recent call last):
[...]
TypeError: from_tuple() missing 1 required positional argument:
'center'
I wrote my class-method but it always results in the error TypeError: from_tuple() missing 1 required positional argument: 'radius'. I can;t find out how to fix this. Any help would be appreciated.
The simplest way would be to create a Point from that tuple and then hand it over to __init__ via cls
#classmethod
def from_tuple(cls, center, radius=1)
return cls(Point(*center), radius)
Here I also give radius a default value, so it's possible to describe a radius 1 circle with only the coordinates of its center, as is the case with your __init__ method

Operating with Python class and objects

I want to create both a Vector class and a Point class and have a function inside the Vector class that is able to add a Vector object and a Point object, but I don't understand how I have to operate with the internal variables of the classes. This is the code I have right now:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def AddVector(self, point):
point2 = Point(0, 0)
point.x + self.x = point2.x
point.y + self.y = point2.y
return point2
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p1 = Point(2,3)
v1 = Vector(4,7)
def main():
Vector.AddVector(p1,v1)
print(point2.x, point2.y)
main()
First, don't use global variables. It is a bad habit. Move them into main.
Then, the main problem, call method on the instances (p1 and v1) and not on classes (Vector and Point). Third, use the returned variable. Therefore:
def main():
p1 = Point(2,3)
v1 = Vector(4,7)
p2 = p1.AddVector(v1)
print(p2.x, p2.y)
The next problem is, this is invalid syntax:
point.x + self.x = point2.x
The correct way to assign is the other way around:
point2.x = point.x + self.x
Then, you have AddVector method on Vector. It should be on a Point and it should receive a Vector as argument.
All together:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def AddVector(self, v):
point2 = Point(0, 0)
point2.x = self.x + v.x
point2.y = self.y + v.y
return point2
def main():
p1 = Point(2,3)
v1 = Vector(4,7)
p2 = p1.AddVector(v1)
print(p2.x, p2.y)
main()
Of course, it could be nicer, this is more advanced, but here it is for completeness:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return 'Vector({}, {})'.format(self.x, self.y)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, v):
return Point(self.x + v.x, self.y + v.y)
def __repr__(self):
return 'Point({}, {})'.format(self.x, self.y)
def main():
p1 = Point(2,3)
v1 = Vector(4,7)
p2 = p1 + v1
print(p2)
main()

Move points and check specific start value, using classes python

I need to be able to move points and check a specific point value. This is the code:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def move(self)
#Here I want to move my points
Next class is a linestring. It must be able to handle x set of points
class LineString(Point):
def __init__(self, *points):
self.points = []
for point in points:
if not isinstance(point, Point):
point = Point(*point)
self.points.append(point)
def __getitem__(self):
#Here I want to inspect the value of the specific
# e.g. y value for the start point after it has been moved
I'm a bit unsure of how to get the __getitem__ to work and whether it's in the right position. Should it be under class Point? Could this be done in another way?
Edited code;
from numpy import sqrt
import math
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def dist(self, point):
return math.hypot(self.x - point.x, self.y - point.y)
def move(self, dx, dy):
self.x = self.x + dx
self.y = self.y + dy
class LineString(Point):
def __init__(self, *points):
self.points = []
for point in points:
if not isinstance(point, Point):
point = Point(*point)
self.points.append(point)
def length(self):
return sum(p1.dist(p2) for p1, p2 in zip(self.points[1:], self.points[:-1]))
def move (self, x, y):
for p in self.points:
p.move(x, y)
def __getitem__(self, key):
return self.points[key]
I think this is roughly what you want:
You don't seem to actually need a dictionary (for a line, I think a list makes more sense anyway). So the Line class is just a list of Points, and it provides a move_all_points function to translate them all. Because Line subclasses a list, you get all the standard behaviour of lists for free:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "<Point({},{})>".format(self.x, self.y)
def __str__(self):
return(repr(self))
def move(self, dx, dy):
"""Move the point by (dx, dy)."""
self.x += dx
self.y += dy
class Line(list):
"""A list of points that make up a line."""
def move_all_points(self, dx, dy):
for p in self:
p.move(dx, dy)
So then you can use them as follows:
>>> p1, p2, p3 = Point(0, 0), Point(5, 0), Point(10, 10)
>>> my_line = Line((p1, p2, ))
>>> print my_line
[<Point(0,0)>, <Point(5,0)>]
>>> my_line.append(p3)
>>> print my_line
[<Point(0,0)>, <Point(5,0)>, <Point(10,10)>]
>>> p4 = Point(100,100)
>>> my_line.move_all_points(1, 1)
>>> print my_line
[<Point(1,1)>, <Point(6,1)>, <Point(11,11)>]
>>> my_line.append(p4)
>>> print my_line
[<Point(1,1)>, <Point(6,1)>, <Point(11,11)>, <Point(100,100)>]

Rotation matrix scales down

I'm trying to build some micro "3d engine" as to understand the basics of this field.
Everything works quite fine except for rotations. I use the standard rotation matrices to do this, yet all 3 of the possible rotations not only rotate the points, they also scale them down. This behaviour is not intended or wished for.
Following is the relevant part of the code (I think):
class Point:
def __init__(self, x, y, z, ui):
self.x = mpf(x)
self.y = mpf(y)
self.z = mpf(z)
self.ui = ui
def subtractVectorFromPoint(self, vector):
self.x -= vector.x
self.y -= vector.y
self.z -= vector.z
return self
def subtractPointFromPoint(self, point):
TempVector = Vector(0, 0, 0)
TempVector.x = self.x - point.x
TempVector.y = self.y - point.y
TempVector.z = self.z - point.z
return TempVector
def setPointToPoint(self, point):
self.x = point.x
self.y = point.y
self.z = point.z
return self
class Vector:
def __init__(self, x, y ,z):
self.x = mpf(x)
self.y = mpf(y)
self.z = mpf(z)
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
self.x = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
return self
#rotate xy plane by 15 degrees on pressing r
if event.key == pygame.K_r:
origin = Vector(0, 0, 0)
UI.draw_background()
for point in pointList:
tempVector = point.subtractPointFromPoint(origin)
point.setPointToPoint(origin)
point.addVectorToPoint(tempVector.rotateXY(15))
point.drawPoint()
That should be all you need I think. Any pointers to where I went wrong are welcome.
I know the classes miss an indent in the example here, I suck at the layout on this website :)
p.s. I tried using the "mpf()" function to increase the precision but this had 0 result.
The problem is in this part:
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
self.x = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
return self
self.y is being calculated using a self.x that is already adjusted, resulting in given problem.
A fix for this is using a temp variable like this:
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
tempX = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
self.x = tempX
return self

Not recognizing object parameter as int

class Ball:
def __init__(self,pos,vel):
self.pos = Vector(pos.x,pos.y)
self.vel = Vector(vel.x,vel.y)
def curx(self):
return (self.pos.x + self.vel.x)
def cury(self):
return (self.pos.y + self.vel.y)
def forcex(velx):
self.vel.deltax(velx)
def forcey(vely):
self.vel.deltay(vely)
class Vector:
def __init__(self,x,y):
self.x = x
self.y = y
def x(self):
return self.x
def y(self):
return self.y
def delx(self,deltax):
self.x = self.x + deltax
def dely(self,deltay):
self.y = self.y + deltay
Here are my two classes, but when I initialize and try to get curx or cury back from ball:
ball = Ball(Vector(0,0),Vector(0,0))
print ball.curx
I get: <bound method Ball.curx of <__main__.Ball instance at 0x1142fd0>>
I feel like there should be a fairly simple answer to this and I'm just not getting it.
curx is a method of Ball. So, you have to invoke it:
print ball.curx()
Edit:
#user2357112 has noticed two more problems:
The definitions of Ball.forcex and Ball.forcey are missing their self parameters.
Vector.x and Vector.y are entirely useless methods. You already have x and y as attributes of Vector through self.x and self.y. So, you should just remove the methods altogether.
Here is how the code should be:
class Ball:
def __init__(self,pos,vel):
self.pos = Vector(pos.x,pos.y)
self.vel = Vector(vel.x,vel.y)
def curx(self):
return (self.pos.x + self.vel.x)
def cury(self):
return (self.pos.y + self.vel.y)
def forcex(self, velx):
self.vel.deltax(velx)
def forcey(self, vely):
self.vel.deltay(vely)
class Vector:
def __init__(self,x,y):
self.x = x
self.y = y
def delx(self,deltax):
self.x = self.x + deltax
def dely(self,deltay):
self.y = self.y + deltay
ball = Ball(Vector(0,0),Vector(0,0))
print ball.curx()

Categories