I am new to python and I am trying to write class RectangleCollection. class Rectangle is given, and I need to write class RectangleCollection part.
class RectangleCollection has one list instance variable, rectangles, that should initially refer to an empty list.
get_same_area_rects takes a number as a parameter and returns a list of all Rectangles from the rectangles list that have that area.
class Rectangle:
""" A rectangle with a width and height. """
def __init__(self, w, h):
""" (Rectangle, number, number)
Create a new rectangle of width w and height h.
>>> r = Rectangle(1, 2)
>>> r.width
1
>>> r.height
2
"""
self.width = w
self.height = h
def area(self):
""" (Rectangle) -> number
Return the area of this rectangle.
>>> r = Rectangle(10, 20)
>>> r.area()
200
"""
return self.width * self.height
These are what I have done :
class RectangleCollection:
def __init__(self):
""" (RectangleCollection) -> NoneType
>>> rc = RectangleCollection()
>>> rc.rectangles
[]
"""
self.rectangles = []
def get_same_area_rects(self, number):
"""
>>>rc = RectangleCollection()
>>>r1 = Rectangle(10, 20)
>>>r2 = Rectangle(15, 20)
>>> r3 = Rectangle(20, 10)
>>>rc.rectangles.extend([r1, r2, r3])
>>>res = rc.get_same_area_rects(200)
>>>res == [r1, r3]
True
"""
self.number = number
a = self.rectangles.expend(self.area())
if number == self.rectangles.area():
return True
return False
but for get_same_area_rects part, I always get False..
I have no idea what I did wrong. Please help
i think it is because rc.rectangles gives me r1,r2,r3 addresses, not the areas. I should get [200,300,200] but I get the addresses. I think this is why I always get False.. How can I fix this problem?
How about use filter function to only take rectangles whose area is number
def get_same_area_rects(self, number):
return filter(lambda rect: rect.area() == number, self.rectangles)
CSC108 right? This function within class is not asking you to return True of False, it is asking you to call this function to get a list of rectangles that their area is 200
You have a typographic error in your code. It should be:
extend not expend as follows:
a = self.rectangles.extend(self.area())
if number == self.rectangles.extend(self.area()):
return True
Or simply:
a = self.rectangles.extend(self.area())
if number == a:
return True
You have to create a temporary list and then loop over the rectangles. This is because since we have to return a list which has the same area, we would need to use the rectangle.area() to compare if they are true or not and then add into the list.
def get_same_area_rects(self, number):
temp_list = []
for rectangle in self.rectangles:
if number == rectangle.area():
temp_list.append(rectangle)
return temp_list
hope it helps :)
Related
I am working on a simple cuboid class program in python and I am very new to it all so I have a few questions about the first version of my code:
from math import *
class Cuboid:
def __init__(self,length,width,height):
self.length=length
self.width=width
self.height=height
self.LSA=0
self.SA=0
self.volume=0
def getDimensions(self):
return self.length
return self.width
return self.height
def LateralSurfaceArea(self):
LSA=2*((self.length*self.height)+(self.width*self.height))
return LSA
def SurfaceArea(self):
SA=2*((self.length*self.width)+(self.width*self.height)+(self.height*self.length))
return SA
def Volume(self):
Volume=self.length*self.width*self.height
return volume
My first question, is this the proper way to set up a class and initialize it?
second question, are there any glowing errors in this part? I am working out of a textbook teaching myself and it has no examples.
Finally my main:
from cuboid import *
def main():
cb = Cuboid(3, 4, 5)
l, w, h = cb.getDimensions()
print("The length of the cuboid is", l)
print("The width of the cuboid is", w)
print("The height of the cuboid is", h)
print("lateral surface area=", cb.LateralSurfaceArea())
print("surface area=", cb.SurfaceArea())
print("volume=", cb.Volume())
main()
when I run my main function I get the following error:
l, w, h = cb.getDimensions()
TypeError: 'int' object is not iterable
Does anyone have any idea why this error is coming up and anyway I can get around it? sorry I know I'm only supposed to ask a specific question but for the sake of learning properly id rather make sure I'm going in the right direction as classes are new to me.
When returning multiple values, you don't use multiple return statements. Instead, you return a tuple:
return (self.length, self.width, self.height)
In your case, only the first return statement gets executed thus passing a single int to the caller. It then tries to unpack that value into the three variables you specified by iterating over it. The single value that was returned isn't iterable, hence the error.
A slightly cleaned-up version:
class Cuboid:
def __init__(self, length, width, height):
self.length = length
self.width = width
self.height = height
#property
def lateral_surface_area(self):
front_area = self.length * self.height
side_area = self.width * self.height
return 2 * (front_area + side_area)
#property
def surface_area(self):
top_area = self.length * self.width
front_area = self.length * self.height
side_area = self.width * self.height
return 2 * (top_area + front_area + side_area)
#property
def volume(self):
return self.length * self.width * self.height
def main():
cube = Cuboid(3, 4, 5)
print("The length of the cuboid is", cube.length)
print("The width of the cuboid is", cube.width )
print("The height of the cuboid is", cube.height)
print("Lateral surface area =", cube.lateral_surface_area)
print("Surface area =", cube.surface_area)
print("Volume =", cube.volume)
if __name__=="__main__":
main()
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))
..trying to define a method within my Point Class that checks interaction with objects of my Rectangle class on interior or boundary using type based dispatch. I tried the code below, but yields: AttributeError: 'set' object has no attribute 'intersects'.
Also, seeking a way to clearly set what intersects at boundary vs. interior. Please advise.
class Point(object):
def __init__(self, x, y, height=0):
self.x = float(x)
self.y = float(y)
self.height = float(height)
def intersects(self, other):
if isinstance(other, Point):
s1=set([self.x, self.y])
s2=set([other.x, other.y])
if s1.intersection(s2):
return True
else:
return False
elif isinstance(other, Rectangle):
s1=set([self.x, self.y])
s2=set(other.pt_ll, other.pt_ur)
if s1.intersection(s2):
return True
else:
return False
class Rectangle(object):
def __init__(self, pt_ll, pt_ur):
"""Constructor.
Takes the lower left and upper right point defining the Rectangle.
"""
self.ll = pt_ll
self.lr = Point(pt_ur.x, pt_ll.y)
self.ur = pt_ur
self.ul = Point(pt_ll.x, pt_ur.y)
these are my calling statements:
pt0 = (.5, .5)
r=Rectangle(Point(0, 0),Point(10, 10))
s1 = set([pt0])
s2 = set([r])
print s1.intersects(s2)
it would be intersection() s1.intersection(s2), you are using a set not a Point object:
s1 = set([pt0]) # <- creates a python set
To use your intersects method you need Point objects:
p = Point(3,5) # <- creates a Point object that has intersects method
p2 = Point(3,5)
print(p.intersects(p2))
So using your example, you need to access the Point objects using the attributes of the Rectangle class:
r = Rectangle(Point(0, 0),Point(10, 10))
print(r.lr.intersects(r.ul)) # <- the Rectangle attributes lr and ul are Point objects because you passed in Point's when you initialised the instance r
You can simplify the assignments in Rectangle:
class Rectangle(object):
def __init__(self, pt_ll, pt_ur):
"""Constructor.
Takes the lower left and upper right point defining the Rectangle.
"""
self.lr = Point(pt_ur.x, pt_ll.y)
self.ul = Point(pt_ll.x, pt_ur.y)
You can also just use set literals:
s1 = {self.x, self.y}
s2 = {other.x, other.y}
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()
I'm trying to write a code that will display a shape from tetris on a board. I keep getting this error and don't know how to fix it:
TypeError: unbound method can_move() must be called with O_shape instance as first argument (got Board instance instead)
Here is my code:
class Board():
def __init__(self, win, width, height):
self.width = width
self.height = height
# create a canvas to draw the tetris shapes on
self.canvas = CanvasFrame(win, self.width * Block.BLOCK_SIZE + Block.OUTLINE_WIDTH,
self.height * Block.BLOCK_SIZE + Block.OUTLINE_WIDTH)
self.canvas.setBackground('light gray')
# create an empty dictionary
# currently we have no shapes on the board
self.grid = {}
def draw_shape(self, shape):
''' Parameters: shape - type: Shape
Return value: type: bool
draws the shape on the board if there is space for it
and returns True, otherwise it returns False
'''
if shape.can_move(self, 0, 0):
shape.draw(self.canvas)
return True
return False
class Tetris():
SHAPES = [I_shape, J_shape, L_shape, O_shape, S_shape, T_shape, Z_shape]
DIRECTION = {'Left':(-1, 0), 'Right':(1, 0), 'Down':(0, 1)}
BOARD_WIDTH = 10
BOARD_HEIGHT = 20
def __init__(self, win):
self.board = Board(win, self.BOARD_WIDTH, self.BOARD_HEIGHT)
self.win = win
self.delay = 1000 #ms
# sets up the keyboard events
# when a key is called the method key_pressed will be called
self.win.bind_all('<Key>', self.key_pressed)
# set the current shape to a random new shape
self.current_shape = self.create_new_shape()
# Draw the current_shape oan the board
self.board.draw_shape(self.current_shape)
def create_new_shape(self):
''' Return value: type: Shape
Create a random new shape that is centered
at y = 0 and x = int(self.BOARD_WIDTH/2)
return the shape
'''
# YOUR CODE HERE
y = 0
x = int(self.BOARD_WIDTH/2)
the_shape = random.choice(self.SHAPES)
return the_shape
you didn't post the code for the relevant method (can_move()).
besides, the error message is self explanatory, it expects a parameter of type O_shape but you're calling the method and passing it a Board instead.
def draw_shape(self, shape):
''' Parameters: shape - type: Shape
Return value: type: bool
draws the shape on the board if there is space for it
and returns True, otherwise it returns False
'''
if shape.can_move(self, 0, 0): # <-- you probably meant to call shape.can_move(0,0)
shape.draw(self.canvas)
return True
return False
methods that are bound to a class have the instance passed as the first parameter implicitly.
You forgot to instantiate your shape classes.
SHAPES = [I_shape(), J_shape(), L_shape(), O_shape(), S_shape(), T_shape(), Z_shape()]
But you should only have a single Shape class that takes arguments to turn them into the various shapes.