Finding Geometric Objects Perimeter and Area using subclasses - python

I have a lab assignment in my Python Programming class that I am having a little trouble with. Our instructor gave us source code GeometricObject.py as a reference.
class GeometricObject(object):
def __init__(self, color = "white", filled = True):
self.color = color
self.filled = filled
def getColor(self):
return self.color
def setColor(self, color):
self.color = color
def isFilled(self):
return self.filled
def setFilled(self, filled):
self.filled = filled
def __str__(self):
return "color: " + self.color + \
" and filled: " + str(self.filled)
Now I'm supposed to use this class, to create a subclass that applies this information to different objects. I have to make a class to calculate the area and perimeter among other things of a circle, as well as a triangle.
I am having trouble understanding when I need to copy and paste from the source code or if I don't need to. Here is the first class I made, that deals with a Circle. Simple question: Is it named correctly? Should the class be called GeometricObject(circle):???
import math
class GeometricObject(object):
'''Class using a Circle'''
def __init__(self, color = "white", filled = True):
self.radius = 1
self.color = color
self.filled = filled
def getColor(self):
return self.Color
def setColor(self, color):
self.color = color
def isFilled(self):
return self.filled
def setFilled(self, filled):
self.filled = filled
def getArea(self):
self.area = math.pi(self.radius)**2
return self.area
def getPerimeter(self):
r = radius
self.perimeter = 2(math.pi)(r)
return self.perimeter
def __str__(self):
return "color: " + self.color + \
" and filled: " + str(self.filled)
Note: In the def_str_ method, It is supposed to print Circle: radius = 3 color: red and filled: True" even though it previously states to set the default values as 1, and the color: white. I am confused by this.
That's pretty much the jist of it. I'm hoping my coding is correct so far!
I then have to do the same thing for the Triangle class, but I'm pretty sure it's similiar.
class GeometricObject(object):
'''Class using a Triangle'''
def __init__(self, color = "white", filled = True):
self.side1 = 1
self.side2 = 1
self.side3 = 1
def getArea(self):
s = (self.side1 + self.side2 + self.side3)/2
area = math.sqrt(s(s - self.side1)(s - self.side2)(s - self.side3))
return area
def getPerimeter(self)
perimeter = self.side1 +self.side2 + self.side3
return perimeter
def __str__(self):
return "color: " + self.color + \
" and filled: " + str(self.filled)
def getColor(self):
return self.Color
def setColor(self, color):
self.color = color
def isFilled(self):
return self.filled
def setFilled(self, filled):
self.filled = filled
So I guess my main questions are:
+Am I supposed to copypaste the source code from GeometricObject() over and over, or is it already there?
+The string method is confusing to me because it is asking for different values than previously specified.
+The code. I think I implemented the area and perimeter formulas for each correctly?
Thanks in advance. Any help is greatly appreciated!!

I think you want to do it like this:
class Circle(GeometricObject):
.
.
.
class Triangle(GeometricObject):
.
.
.
You only need to implement those things in the Circle and Triangle classes that are different from the GeometricObject class.

Vaughn's got the right idea on subclassing Geometric Objects, but check your work on the getArea function:
s(s - self.side1)
will raise the following traceback:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

In order to use the GeometricObject.py file you're going to want to import the file so that you can access it's methods, make sure that both files are in the same directory:
import GeometricObject from GeometricObject
Put that at the top of your current file if you wish to keep it separate. You can also simply copy-paste the source code from that file as well if you wish.
Next, you're going to want to create the class of GeometricObject. In Python, it is implied that any class that does not have a specified inheritance has object as it's superclass. The cleanest way to write out this problem would be simply:
class GeometricObject:
instead of
class GeometricObject(object):
All following classes that wish to inherit the methods in the GeometricObject class would be written like this. You must include
super().__init__()
in your initializer for your subclass in order to initialize all the data fields in the GeometricObject superclass so that you can use them. That way you can delete the isFilled and getColor and setColor methods out of your Triangle class and keep them in your GeometricObject class.
class Triangle(GeometricObject):
def __init__(self, color = "white", filled = True):
super().__init__()
-
-
-
class Circle(GeometricObject):
-
-
-
Also, keep an eye out for
area = math.sqrt(s(s - self.side1)(s - self.side2)(s - self.side3))
This will return an error. In Python (x)(x) does not mean x * x. This instead will need to be written out like:
area = math.sqrt(s*(s - self.side1)*(s - self.side2)*(s - self.side3))

Related

adding two values from different classes

class PolygonInteriorAngle(object):
def __init__(self, x):
self.x = self
def FindInteriorAngle(self):
degrees = int((x - 2) * 180)
interior = int(degrees / x)
return interior
def PrintInterior(self):
print("interior angle: " + str(self.FindInteriorAngle()))
class PolygonExteriorAngle(object):
def __init__(self, x):
self.x = self
def FindExteriorAngle(self):
exterior = int(360 / x)
return exterior
def PrintExterior(self):
print("exterior angle: " + str(self.FindExteriorAngle()))
class AngleAddition(object):
def __init__(self, x):
self.x = self
def Add(self):
sum = int(interior + exterior)
return sum
def PrintAdd(self):
print("sum of interior and exterior: " + str(self.Add()))
if __name__ == "__main__":
x = int(input("enter: "))
intObj = PolygonInteriorAngle(x)
intObj.FindInteriorAngle()
intObj.PrintInterior()
extObj = PolygonExteriorAngle(x)
extObj.FindExteriorAngle()
extObj.PrintExterior()
addObj = AngleAddition(x)
addObj.Add()
addObj.PrintAdd()
both classes (PolygonInteriorAngle and PolygonExteriorAngle) work fine, they print what they're expected to. what i want to do in the AngleAddition class is to add both of the final values (interior and exterior) that you get from the other two classes. i think it's pretty inefficient putting them in different classes, but that's what my computer science teacher asked me to and i'm not sure how to use a value from another class in a new class. if you do x = 6, you'll get 120 and 60. with AngleAddition i want to print 180.
General comments:
You need to check very carefully the variables in your instance methods. example:
def Add(self):
sum = int(interior + exterior)
return sum
Both interior and exterior are not specified in the instance method arguments.
I agree with User: Tim Roberts's comment. Either you make a base class "angle" and let the "interior/exterior angle" class inherit from the "angle" class, or just use angle class for both interior/exterior angles. It depends on how you want to write the __init__ method for interior/exterior angle classes.
Note that I overrode the magic method to perform the sum of two angles. There are other ways of doing that cause in my way the + operator is being redefined.
Anyways:
class AngleBase:
def __init__(self,angle):
self.angle=angle
def __add__(self,angleobj):
return int(self.angle+angleobj.angle)
class PolygonInteriorAngle(AngleBase):
def __init__(self, side):
degrees = int((side - 2) * 180)
interior = int(degrees / side)
AngleBase.__init__(self,interior)
def FindInteriorAngle(self):
return self.angle
def PrintInterior(self):
print("interior angle: " + str(self.angle))
class PolygonExteriorAngle(AngleBase):
def __init__(self, side):
exterior = int(360 / side)
AngleBase.__init__(self,exterior)
def FindExteriorAngle(self):
return self.angle
def PrintExterior(self):
print("exterior angle: " + str(self.angle))
class AngleAddition:
def __init__(self, x):
pass
def Add(self,interior, exterior):
sum = int(interior + exterior)
return sum
def PrintAdd(self,interior, exterior):
print("sum of interior and exterior: " + str(self.Add(interior, exterior)))
if __name__ == "__main__":
x = int(input("enter: "))
intObj = PolygonInteriorAngle(x)
print(intObj.angle)
intObj.FindInteriorAngle()
intObj.PrintInterior()
extObj = PolygonExteriorAngle(x)
extObj.FindExteriorAngle()
extObj.PrintExterior()
addObj = AngleAddition(x)
addObj.Add(extObj,intObj)
addObj.PrintAdd(extObj,intObj)

How to access a child class method from a parent class?

There are a lot of answers saying this is unadvisable, but I found a scenario where I think it's useful. Please correct me if I'm wrong and there's a better way.
I'm building a chess game, where individual pieces inherit from the superclass Chesspiece:
class ChessPiece:
def __init__(self, pos, color, num, piece):
...
Each piece has a method that defines the moves it can take:
class Knight(ChessPiece):
def __init__(self, pos, color=None, num=''):
ChessPiece.__init__(self, pos, color, num, self.__class__.__name__)
def possible_moves(self):
pos_moves = []
# Up, Right (1 space, 2 spaces)
try:
if 1 <= self.x + 2 <= len(Config.board) and 1 <= self.y - 1 <= len(Config.board):
if Config.board[self.x + 2][self.y - 1] == '___':
pos_moves.append(f'{Config.tile_convert(self.x + 2)}{Config.tile_convert(self.y - 1, True)}')
except Exception: pass
#Up, Left
...
return pos_moves
I'd like to implement a move() function. The code for the move() function will be the same for each piece, except for the fact that it has to compare the suggested move with the possible moves, which vary for each piece. I could make a move() function for each piece, but that would just be repeating code 6 times.
So, I'd like to define move() in Chesspiece and reference each piece's possible_moves() function.
It is simpler to implement an empty possible_moves in the parent:
class ChessPiece:
...
def possible_moves(self):
raise NotImplementedError
def move(self, pos):
if pos in self.possible_moves():
...
Or even return an empty set of movements in the parent class:
def possible_moves(self):
return set()
But I think the first is better, so it forces all subclasses to implement it in order to been useful.

class Rectangle - Python

I'm just beginning working with object-oriented programming. I have created some classes and am trying to complete the rectangle class. Any and all help is appreciated.
I'm confused about when you need to refer to self and when you can just create variables. For example, in defining the length of the rectangle, I don't know if I should call the variable self.length or just length, and I haven't been able to find any rectangle classes defined in this way.
import math
class Point (object):
# constructor
def __init__ (self, x = 0, y = 0):
self.x = x
self.y = y
# get distance
def dist (self, other):
return math.hypot (self.x - other.x, self.y - other.y)
# get a string representation of a Point object
def __str__ (self):
return '(' + str(self.x) + ", " + str(self.y) + ")"
# test for equality
def __eq__ (self, other):
tol = 1.0e-16
return ((abs (self.x - other.x) < tol) and (abs(self.y - other.y) < tol))
class Circle (object):
# constructor
def __init__ (self, radius = 1, x = 0, y = 0):
self.radius = radius
self.center = Point (x, y)
# compute cirumference
def circumference (self):
return 2.0 * math.pi * self.radius
# compute area
def area (self):
return math.pi * self.radius * self.radius
# determine if point is strictly inside circle
def point_inside (self, p):
return (self.center.dist(p) < self.radius)
# determine if a circle is strictly inside this circle
def circle_inside (self, c):
distance = self.center.dist (c.center)
return (distance + c.radius) < self.radius
# determine if a circle c intersects this circle (non-zero area of overlap)
def does_intersect (self, c):
# string representation of a circle
def __str__ (self):
# test for equality of radius
def __eq__ (self, other):
tol = 1.0e-16
class Rectangle (object):
# constructor
def __init__ (self, ul_x = 0, ul_y = 1, lr_x = 1, lr_y = 0):
if ((ul_x < lr_x) and (ul_y > lr_y)):
self.ul = Point (ul_x, ul_y)
self.lr = Point (lr_x, lr_y)
else:
self.ul = Point (0, 1)
self.lr = Point (1, 0)
# determine length of Rectangle
def length (self):
# determine width of Rectangle
def width (self):
# determine the perimeter
def perimeter (self):
# determine the area
def area (self):
# determine if a point is strictly inside the Rectangle
def point_inside (self, p)
# determine if another Rectangle is inside this Rectangle
def rectangle_inside (self, r):
# determine if two Rectangles overlap
def does_intersect (self, other):
# determine the smallest rectangle that circumscribes a circle
def rect_circumscribe (self, c):
# give string representation of a rectangle
def __str__ (self):
# determine if two rectangles have the same length and width
def __eq__ (self, other):
Basically, setting a value to self.length gives you the ability to access this value from other functions inside the class and from outside of the class. If you set a value to length, you are able to access this variable only in the current function inside the class.
Just a start, try to continue yourself:
class Rectangle (object):
# constructor
def __init__ (self, ul_x = 0, ul_y = 1, lr_x = 1, lr_y = 0):
# Called if you say: my_rectancle = Rectangle (-10, 10, 10, -10)
# Puts parameters in fields of your newly created object of class Rectancle
self.ul_x = ul_x
self.ul_y = ul_y
self.lr_x = lr_x
self.lr_y = lr_y
# compute cirumference
def circumference (self):
return 2 * (self.ur_x - self.lr_x) + 2 * (self.ul_y - self.lr_y)
# compute area
def area (self):
return (self.ur_x - self.lr_x) * (self.ul_y - self.lr_y)
[EDIT]
With regard to the additional code in your comment, it's quite close to what it should be. With some corrections:
# determine length of Rectangle
def length (self):
return self.ul_y - self.lr_y
# determine width of Rectangle
def width (self):
return self.lr_x - self.ul_x
# self. has been added, since e.g. lr_x is not a parameter
# of the width function, but a field of the object you make
# by instantiation: 'rectangle = Rectangle (10, 20, 100, 200)'
# After that, self refers to the object 'rectangle' you created,
# which has class 'Rectangle'.
#
# Note that a class is a type.
# You can have a type 'Dog'.
# Dog 'fluffy' is an instance of that class, so a particular dog.
# In the methods (functions) of 'Dog', 'self' refers to the particular
# dog you're working with.
# determine the perimeter
def perimeter (self):
return 2 * self.width () + 2 * self.length ()
# Note the () after width and length.
# They're needed because width and length are
# function calls (they DO something) rather than fields (data)
# You could also have stored width and length into fields,
# just like the constructor did with ul_x, ul_y, lr_x and lr_y,
# storing them in self.ul_x, self.ul_y etc.
# Then the braces wouldn't have been needed.
# But also out some superfluous braces here
# Multiplication goes before addition anyhow
# And return returns everything after it, no braces needed.
# determine the area
def area (self):
return self.width () * self.length ()
So, how far did you get now?

How would I get this value? (Python)

I have
class Point:
def __init__(self, initX, initY):
self.x = initX
self.y = initY
def getX(self):
return self.x
def getY(self):
return self.y
def __str__(self):
return "x=" + str(self.x) + ", y=" + str(self.y)
class Rectangle:
def __init__(self, initP, initW, initH):
self.__location = initP
self.__width = initW
self.__height = initH
def getWidth(self):
return self.__width
def getHeight(self):
return self.__height
def getLocation(self):
return self.__location
#---------------------------------------------------------------
#string
def __str__(self):
return "x=" + str(self.__location.x) + ", y=" + str(self.__location.y) +", Width=" + str(self.getWidth()) + ", Height=" +str(self.getHeight())
def area(self):
return self.getWidth() * self.getHeight()
def calculatePerimeter(self):
return self.getWidth()*2 +self.getHeight()*2
def transpose(self):
temp = self.__width
self.__width = self.__height
self.__height = temp
def encloses(self, otherP):
return ((self.getWidth() + self.getLocation().getX()) > otherP.getX()\
and (self.getLocation().getX()) <otherP.getX() \
and (self.getHeight() + self.getLocation().getY()) >otherP.getY()\
and self.getLocation().getY() < otherP.getY())
def computeDiagonal(self):
d = (self.getWidth()**2 + self.getHeight()**2) ** 0.5
return d
def detectCollision(firstRectangle, secondRectangle):
print(firstRectangle.getWidth())
print(secondRectangle)
first = Rectangle(Point(1,0), 4, 3)
second = Rectangle(Point(4,0), 4, 3)
Rectangle.detectCollision(first, second)
I am trying to detect a collision. I'm a bit stuck. (detectCollision)
I am having trouble getting the value from the point class to the rectangle class.
Does anybody have any idea?
The function detectCollision is wrong. I was testing and I could get the width, and the height with getHeight() but I could not get the values inside Point.
I am having trouble getting the value from the point class to the rectangle class.
I think you need to read through a good tutorial on classes. Maybe the chapter in the official tutorial, or maybe a third-party tutorial. StackOverflow is not a good place to learn basic concepts.
You don't actually want to get a value from the point class, you want to get the value from a particular point instance. After all, there are lots of points in the world, and each one has different x and y values, and you're trying to check if some particular point has collided with the rectangle.
How do you know which instance? You take one as a parameter. And then you can access that object's members, methods, etc., just like you do with a string or any other object.
class Rectangle(object):
# existing stuff
def collision_check(self, point):
return (self.left <= point.getX() <= self.right and
self.top <= point.getY() <= self.bottom)
That's it.
Except that you probably don't want getX and getY methods in the first place; better to just do point.x and point.y.
Also, I've obviously had to make some assumptions about how you defined Rectangle (left/top/bottom/right? left/right/width/top? topleftpoint/bottomrightpoint?) and about what you mean by "collision" (hitting the edge of the rectangle, or the interior of the rectangle?), etc., since you didn't explain any of that. But hopefully you can adapt this to whatever your actual design is.
So, how do you use this? You just pass a point as an argument to the method, same as you do with, say, len:
>>> rect = Rectangle(10, 10, 20, 20)
>>> point1 = Point(5, 5)
>>> rect.collision_check(point1)
False
>>> point2 = Point(15, 15)
>>> rect.collision_check(point2)
True
Now that you've shown us more of your code, it looks like you're trying to collision-check two rectangles—and, more importantly, your problem is that your rectangle uses a Point as its top-left origin, and you don't know how to access the coordinations of that.
From your description, "I was testing and I could get the width, and the height with getHeight() but I could not get the values inside Point", you seem to still be missing the key issue here. You don't want to get the values inside Point. Point is a class—a factory for creating actual point objects. You want to get the values inside one of those actual point objects, the one you've stored in a rectangle object's __location and made available through a getLocation method. (As I already explained, you should get rid of those getter methods and just have a location attribute, but let's forget that for now.)
So, the way you get the particular point object you're interested in is to call getLocation() on the rectangle, and then the way you get the x and y values for that particular point object is to call its getX and getY methods. So, here's an example of using all those methods:
firstLocation = firstRectangle.getLocation()
firstLeft = firstLocation.getX()
Or you can combine those calls into one expression:
firstLeft = firstRectangle.getLocation().getX()
So, you can do something like this:
def detectCollision(firstRectangle, secondRectangle):
firstLeft = firstRectangle.getLocation().getX()
firstRight = firstLeft + firstRectangle.getWidth()
# similar code for top and bottom, and for second rectangle
return ((firstLeft <= secondLeft <= firstRight or
firstLeft <= secondRight <= firstRight) and
(firstTop <= secondTop <= firstBottom or
firstTop <= secondBottom <= firstBottom))

python 2.7 Instantiating class in another class

I am writing a class, Tbeam (Python 2.7.8 in IPython notebook 2.2.0) that calculates values for a reinforced concrete T beam. The flange and web of the Tbeam are considered to be objects of the class Rectangle. I instantiate a flange and web from the class Rectangle in the class Tbeam, and create methods to calculate the overall depth (d) and area (area) of the Tbeam.
class Rectangle:
"""A class to create simple rectangle with dimensions width (b) and
height (d). """
def __init__(self, b, d ):
"""Return a rectangle object whose name is *name* and default
dimensions are width = 1, height = 1.
"""
self.width = b
self.height = d
def area(self):
"""Computes the area of a rectangle"""
return self.width * self.height
def inertia(self):
"""Computes the moment of inertia of a rectangle,
with respect to the centroid."""
return self.width*math.pow(self.height,3)/12.0
def perim(self):
"""Calculates the perimeter of a rectangle"""
return 2*(self.width+self.height)
def centroid(self):
"""Calculates the centroid of a rectangle"""
return self.height/2.0
def d(self):
"""Returns the height of the rectangle."""
return self.height
def bf(self):
"""Returns the width of the rectangle."""
return self.width
-
class Tbeam:
"""A class to create T beams with dimensions:
bf = width of top flange,
tf = thickness of top flange,
d = height of web,
bw = width of web. """
def __init__(self, bf,tf,d,bw):
self.bf = bf
self.tf = tf
self.d = d
self.bw = bw
self.flange = Rectangle(bf,tf)
self.web = Rectangle(bw,d)
def area(self):
area =self.flange.area + self.web.area
def d(self):
"""Returns the total height of the Tbeam"""
return self.flange.d + self.web.d
-
When I execute the test cell
# Test Tbeam
t1 = Tbeam(60.0, 5.0,27.0,12.0)
print t1.d
print t1.area
-
I get the following:
27.0
bound method Tbeam.area of <__main__.Tbeam instance at 0x7f8888478758
27.0 is correct but I do not understand the second response for print t1.area. I assume my definition for area is incorrect but I don't know how to correct the problem.
Many thanks
Ron
You're printing t1.area which is a method. You want to print the result of calling the method, so print t1.area().
area method is defined as
def area(self):
area =self.flange.area + self.web.area
but should be defined as
def area(self):
area =self.flange.area() + self.web.area()

Categories

Resources