In [1]:
class Point:
    """Represents a point in 2-D space."""

In [2]:
Point


Out[2]:
__main__.Point

In [3]:
blank = Point()
blank


Out[3]:
<__main__.Point at 0x7f49502f3eb8>

In [4]:
blank.x = 3.0
blank.y = 4.0

In [5]:
dir(blank)


Out[5]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'x',
 'y']

In [6]:
def print_point(p: Point) -> None:
    print("({:g}, {:g})".format(p.x, p.y))

print_point(blank)


(3, 4)

In [7]:
class Rectangle:
    """Represents a rectangle.
    attributes: width, height, corner.
    """

In [8]:
box = Rectangle()
box.width = 100.0
box.height = 200.0
box.corner = Point()
box.corner.x = 0.0
box.corner.y = 0.0

In [9]:
def find_center(rect: Rectangle) -> Point:
    p = Point()
    p.x = rect.corner.x + rect.width/2
    p.y = rect.corner.y + rect.height/2
    return p

In [10]:
center = find_center(box)
print_point(center)


(50, 100)

In [11]:
def grow_rectangle(rect: Rectangle, dwidth: float, dheight: float) -> None:
    rect.width += dwidth
    rect.height += dheight

In [12]:
box.width, box.height


Out[12]:
(100.0, 200.0)

In [13]:
grow_rectangle(box, 50, 100)
box.width, box.height


Out[13]:
(150.0, 300.0)

In [14]:
def move_rectangle(rect: Rectangle, dx: float, dy: float) -> None:
    rect.corner.x += dx
    rect.corner.y += dy
    
print_point(box.corner)
move_rectangle(box, 100, 50)
print_point(box.corner)


(0, 0)
(100, 50)

Copy


In [15]:
p1 = Point()
p1.x = 3.0
p1.y = 4.0
import copy
p2 = copy.copy(p1)

In [16]:
print_point(p1)
print_point(p2)
print(p1 is p2)
print(p1 == p2) # behaves as `is` operator


(3, 4)
(3, 4)
False
False

In [17]:
box2 = copy.copy(box) # preserve references
print(box2 is box)
print(box2.corner == box.corner)


False
True

In [18]:
box3 = copy.deepcopy(box) # recursively copy anything
print(box3 is box)
print(box3.corner == box.corner)


False
False

In [19]:
p = Point()
p.x = 3
p.y = 4
#p.z
#---------------------------------------------------------------------------
#AttributeError                            Traceback (most recent call last)
#<ipython-input-19-9b05942bb1b6> in <module>()
#      2 p.x = 3
#      3 p.y = 4
#----> 4 p.z
#
#AttributeError: 'Point' object has no attribute 'z'

In [20]:
type(p)


Out[20]:
__main__.Point

In [21]:
isinstance(p, Point)


Out[21]:
True

In [22]:
print(hasattr(p, 'x'))
print(hasattr(p, 'y'))
print(hasattr(p, 'z'))


True
True
False

In [23]:
try:
    x = p.x
except AttributeError:
    x = 0

print(x)


3