# import packages
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns; sns.set()
A program-defined type is also called a class . A class definition looks like this:
class Point:
"""Represents a point in 2-D space."""
Named elements of an object that are assigned values are known as attributes. In other words, they belong to the object.
class Rectangle:
"""Represents a rectangle.
attributes: width, height, (lower left) corner.
"""
# create an instance of a rectangle
box = Rectangle()
# assign width and height to box
box.width = 100.0
box.height = 200.0
# assign a corner as an instance of a point
box.corner = Point()
# assing x, y to the the corner of the box
box.corner.x = 0.0
box.corner.y = 0.0
def print_point(p):
print('(%g, %g)' % (p.x, p.y))
def print_time(t):
print('%.2d:' % t.hour)
def find_center(rect):
p = Point()
p.x = rect.corner.x + rect.width/2
p.y = rect.corner.y + rect.height/2
return print_point(p)
# return p
find_center(box)
(50, 100)
You can change the state of an object by making an assignment to one of its attributes. For example, what happens if you try to increase the width of a rectangle?
box.width = box.width*2
box.width
200.0
def grow_rectangle(rect, dwidth, dheight):
''' Modifies the width and length of a rectangle by dwidth and dheight
rect: Rectangle object '''
rect.width = rect.width + dwidth
rect.height = rect.height + dheight
grow_rectangle(box, 2, 2)
box.height
202.0
NOTE! Inside the function, rect
is an alias for box, so when the function modifies rect, box changes.
Practice!
move_rectangle
that takes a Rectangle and two numbers named dx
and dy
. It should change the location of the rectangle by adding dx
to the x coordinate of corner and adding dy
to the y coordinate of corner.def move_rectangle(rect, dx, dy):
rect.corner.x = rect.corner.x + dx
rect.corner.y = rect.corner.y + dy
move_rectangle(box, 0,0)
print_point(box.corner)
(0, 0)
Aliasing can make a program difficult to read because changes in one place might have unexpected effects in another place. It is hard to keep track of all the variables that might refer to a given object. Copying an object is often an alternative to aliasing.
import copy
p1 = Point()
p2 = copy.copy(p1)
p1 == p2
False
p1
<__main__.Point at 0x1a1e9c4da0>
p2
<__main__.Point at 0x1a1e9c4dd8>
In order to duplicate an object and embeddings, we want to use deepcopy
. Otherwise, we might accidentally affect multiple objects' embeddings.
box2 = copy.deepcopy(box)
Practice!
move_rectangle
that creates and returns a new Rectangle
instead of modifying the old one.def move_rectangle2(rect1, dx, dy):
rect = copy.deepcopy(rect1)
rect.corner.x = rect.corner.x + dx
rect.corner.y = rect.corner.y + dy
return rect
print_point(box.corner)
(0, 0)
box2 = move_rectangle2(box,1,1)
print_point(box2.corner)
(1, 1)
1. The `Circle` Class
Circle
with attributes center
and radius
, where center
is a Point object and radius is a number.point_in_circle
that takes a Circle and a Point and returns True if the Point lies in or on the boundary of the circle.rect_in_circle
that takes a Circle and a Rectangle and returns True if the Rectangle lies entirely in or on the boundary of the circle.rect_circle_overlap
that takes a Circle and a Rectangle and returns True if any of the corners of the Rectangle fall inside the circle. **Or as a more challenging version, return True if any part of the Rectangle falls inside the circle.
2. Debugging
Investigate the following functions and their uses as they relate to Classes (you may refer to the thinkpython2 book or the interwebs). Briefly give an example of each using the Circle
class you came up with above.
- `type`
- `isinstance`
- `hasattr`