Reputation: 13
In python, I want to create a coordinate system with two classes in separate scripts; lines and points where point class is just x,y and z coordinates and line class then have two of these points as attributes. My problem is that I don't understand how to write line class so it understands it is points it is getting and how to retrieve for example x in a point in line class. Point class looks like this:
class point:
def __init__(self, x, y, z=0):
self.x = float(x)
self.y = float(y)
self.z = float(z)
I am not certain how to write the line class but it looks something like this:
import point
import math
class line(point):
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
def length(self):
return math.sqrt((self.p2.x-self.p1.x)+(self.p2.y-self.p1.y))
Where I should then be able to create objects either like
line = line((1,2), (3,4,5))
or like
p1 = point.point(1,2)
p2 = point.point(3,4,5)
line = line(p1,p2)
I also want to be able to create functions like the one in line class and to retrieve coordinates in something like
line.p2.x
or
line.p2[0]
giving me (in this case) the output of 3. I also don't want point to be a subclass since there can be points not belonging to a line. Perhaps there is already a good answer to how to implement line class in such a way but I haven't found or understood it. Most examples is either about subclasses or separate classes which doesn't send or share some attributes. Thanks in advance for the help.
Upvotes: 1
Views: 1068
Reputation: 52930
First: classes should be title capitalized, so that the proper names would be Line
and Point
- that make them easy to separate from plain variables.
As you've mentioned, inheriting from Point isn't the way to go - since a Line isn't a point. But you're almost there with your example:
from point import Point
import math
class Line:
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
def length(self):
return math.sqrt((self.p2.x-self.p1.x)+(self.p2.y-self.p1.y))
Line(Point(x1, y1), Point(x2, y2)) # should work
You can also use Python 3.6+'s typing support to say that you expect Point objects:
class Line:
def __init__(self, p1: Point, p2: Point):
self.p1 = p1
self.p2 = p2
....
Upvotes: 1
Reputation: 532518
A tuple is not a point
, and line.__init__
will not automatically know to make the conversion. While you could add logic to line.__init__
to detect the type of argument, I would recommend separate functions for creating lines from tuple
s and point
s. Which you choose as the "canonical" argument is up to you. Here's an example using point
.
class Line:
def __init__(self, p1: point, p2: point):
self.p1 = p1
self.p2 = p2
@classmethod
def from_tuples(cls, p1, p2):
return cls(point(*p1), point(*p2))
line1 = Line.from_tuples((1,2), (3,4,5))
p1 = point(1,2)
p2 = point(3,4,5)
line = Line(p1,p2)
Based on how you want to use point
, I would recommend a namedtuple
, and again leave the responsibility to pass the correct type of argument to the caller.
Point = namedtuple('Point', 'x y z')
p1 = Point(1.0, 2.0) # p.x == p[0] == 1
Upvotes: 1