I'm trying to understand OOP (specifically, in Python 3). Here's a basic class template:
class Lines:
"""
Arguments: list of coordinates
"""
def __init__(self, points):
self.x1 = points[0]
self.y1 = points[1]
self.x2 = points[2]
self.y2 = points[3]
I pass starting and ending (x,y) coordinates in a list to the class.
However, I want to also add a length, slope, and y-intercept attribute to the objects of this class Lines (Note: I do not want them as methods). Here are a couple ways I found to do so-
Add to the init method itself
class Lines:
def __init__(self, points):
self.x1 = points[0]
self.y1 = points[1]
self.x2 = points[2]
self.y2 = points[3]
##Create length, slope, and y_intercept attributes
self.length = round(((self.x2-self.x1)**2 + (self.y2-self.y1)**2) ** 0.5, 2)
self.slope = round((self.y2 - self.y1)/(self.x2-self.x1),1)
self.y_intercept = self.y1 - self.slope*self.x1
Create methods for them and use the @property decorator
class Lines:
def __init__(self, points):
self.x1 = points[0]
self.y1 = points[1]
self.x2 = points[2]
self.y2 = points[3]
@property
def length(self):
return round(((self.x2-self.x1)**2 + (self.y2-self.y1)**2) ** 0.5, 2)
@property
def slope(self):
return round((self.y2 - self.y1)/(self.x2-self.x1),1)
@property
def y_intercept(self):
return self.y1 - self.slope*self.x1
My Issues:
I don't prefer the first method (using init()) because it just looks a little cumbersome to fit calculation-based code like that in there. My understanding is that the init method is just there to initialize the attributes of the object and not for much more than that.
I can use the property decorator and then access the objects' slopes etc like so
line1 = Lines([0,0,2,4])
line1.slope
However, when I print line1.__dict__, they are not listed in the attributes available.
My Question
What I really want to know is if there other (more commonly-used, Pythonic) ways to set attributes to the objects(ex: slope) based on the initial attributes(ex: x1,y1). I thought this would be a very common problem (i.e., having a set of basic attributes as input and then setting other more advanced attributes based on them to the same object) but I've not found not much on it on here. I'm sure I'm missing some simple yet elegant solution here.
Thank you in advance. I hope I was clear with my question.
@propertymeans the corresponding function is called every time the property is accessed. Setting the property in__init__sets them once and doesn't ever recalculate. So you need thepropertydecorator on a function if you might be changing the base attributes and need those other properties to always be up to date based on them. But if you don't need that then you may as well set them in the constructor, as it will be slightly more performant.