Defining a Point Class#

For this assignment, you will define a class called Point, which represents the x- and y-position of a point in the Cartesian plane. As such, it should have fields for x and y.

If you need help, the Python documentation is useful: https://docs.python.org/3/tutorial/classes.html, especially section 9.3.

Class Attributes To Define#

The Point class should have the following attributes and methods:

  • A docstring summarizing the class.

  • an __init__ method, which takes parameters x and y and default initializes the attributes x and y to 0.

    • Your class should name the x and y coordinate attributes x and y.

  • a move method, which takes parameters dx and dy and moves the x and y values of the point by those amounts.

  • distance_from, which takes a parameter other_pt and calculates its distance from the current point.

    • Note: there are a variety of functions you might find useful in the math module for this, like sqrt.

Dunder Methods#

In addition to these main methods, please also define a __str__ and a __repr__ method.

At this point, you are probably starting to notice that there are quite a few of these weird things running around whose names start and end with double underscores. The __init__ method above, for example, or the __name__ variable in that funny if __name__ == "__main__": if statement we keep adding at the end of files.

In the world of Python, these are referred to as “dunder” (short for double-underscore) methods. dunder methods are special methods that Python knows to call in special circumstances.

For example, if someone put () after the name of a class name to construct a new instance of an object (e.g., my_point = Point()), Python will immediately look for an __init__ method and call that.

__str__ and __repr__ are similar. When you call str(x) (or put a variable in an f-string, like f"{x}", or call print(x)), Python looks for a __str__ method associated with x and calls that to determine what to print. If you define a __str__ method, then users will be able to call str(one_of_your_point_objects) without you defining a function called str.

Similarly, __repr__ is what Python calls if you just type the name of a variable in Python and hit enter to find out what it should print.

So please also write a __str__ and a __repr__ method for your Point class.

  • Your __str__ method should return the point’s coordinates as a string: "(1, -2)" for a Point object with coordinates(1, -2). To be clear: the __str__ method doesn’t have to print anything — it just has to return a string for Python to print. Printing strings is something Python knows how to do.

    • Note there is a space after the comma between numbers. You can do whatever you want with a __str__ function in normal practice, but the autograder will look for this particular format.

  • Your __repr__ method should return the Class name (in this case, "Point" and coordinates: "Point(1, -2)" for a Point object with coordinates(1, -2). You can just use the literal word "Point" — you don’t have to try and get it from an object attribute. Again, you just need to return a string.

    • Note there is no space between Point and (1, -2) ("Point(1, -2)", or whatever the coordinates happen to be). It doesn’t really matter how you decide to have your class represent itself, but for autograding, we’re lookin for this format.

Scaffolding and Tests#

In a file called point.py, please copy-paste the following code:


import math


class Point:
    # write a docstring here for the class!
    def __init__(self, x=0, y=0):
        # WRITE ME
        pass

    def __str__(self):
        # WRITE ME
        return ""

    def __repr__(self):
        # WRITE ME
        return ""

    def move(self, dx, dy):
        # WRITE ME
        pass

    def distance_from(self, other_pt):
        # WRITE ME
        return 0

    pass


if __name__ == "__main__":
    p1 = Point()
    p2 = Point(3, 4)
    p3 = Point(-3, 4)
    p4 = Point(7, 2)
    p5 = Point(-9, 16)
    points = [p1, p2, p3, p4, p5]
    for pa in points:
        print("---")
        print(pa)
        print(repr(pa))
        for pb in points:
            print(pa.distance_from(pb))
            pass
        pass
    p1.move(1, 1)
    p2.move(-2, 3)
    p3.move(4, -5)
    for pa in points:
        print("---")
        print(pa)
        print(repr(pa))
        for pb in points:
            print(pa.distance_from(pb))
            pass
        pass
    pass

Expected Output#

When you run this code, if your implementation words, the output you get should look something like the output folded below:

---
(0, 0)
Point(0, 0)
0.0
5.0
5.0
7.280109889280518
18.35755975068582
---
(3, 4)
Point(3, 4)
5.0
0.0
6.0
4.47213595499958
16.97056274847714
---
(-3, 4)
Point(-3, 4)
5.0
6.0
0.0
10.198039027185569
13.416407864998739
---
(7, 2)
Point(7, 2)
7.280109889280518
4.47213595499958
10.198039027185569
0.0
21.2602916254693
---
(-9, 16)
Point(-9, 16)
18.35755975068582
16.97056274847714
13.416407864998739
21.2602916254693
0.0
---
(1, 1)
Point(1, 1)
0.0
6.0
2.0
6.082762530298219
18.027756377319946
---
(1, 7)
Point(1, 7)
6.0
0.0
8.0
7.810249675906654
13.45362404707371
---
(1, -1)
Point(1, -1)
2.0
8.0
0.0
6.708203932499369
19.72308292331602
---
(7, 2)
Point(7, 2)
6.082762530298219
7.810249675906654
6.708203932499369
0.0
21.2602916254693
---
(-9, 16)
Point(-9, 16)
18.027756377319946
13.45362404707371
19.72308292331602
21.2602916254693
0.0

You can review the directions in the hearrate_peak exercise for how to compare outputs efficiently with diff if you need.