from math import sqrt

class Point:
    """n-dimensional point
    """

    # notice the function annotations below
    def __init__(self: "Point", coord: [float, ...]) -> None:
        """Initialize this point
        >>> p = Point([3, 4])
        """
        # list comprehensions --- [<expression> for x in iterable]
        # may be something new to you
        self.coord = [float(x) for x in coord]
    
    def distance(self: "Point") -> float:
        """distance from origin
        >>> p = Point([3, 4])
        >>> p.distance()
        5.0
        """
        return sqrt( # square root of...
            sum( # the sum of...
                # squares of elements of self.coord
                [x**2 for x in self.coord]))

    def __eq__(self: "Point", other: "Point") -> bool:
        """
        Return whether self is equivalent to other.

        >>> p1 = Point([3, 4, 5])
        >>> p2 = Point([3.0, 4.0, 5.0])
        >>> p1 == p2
        True
        """
        return (isinstance(other, Point) and # make sure other's a Point and
                len(self.coord) == len(other.coord) and # same lengths and
                # all pairs of corresponding coordinates equivalent
                all([a == b for a, b in zip(self.coord, other.coord)]))

    def set_coord(self: "Points", coord: [float, ]) -> None:
        """Set coordinates for this point"""
        if '_coord' in dir(self): # has _coord already been set?
            raise Exception('Cannot reset coords')
        else: # if not already set, go ahead!
            self._coord = coord

    def get_coord(self: 'Point') -> [float, ...]:
        """Return coordinates for self"""
        return self._coord
        
    # Access to coord is delegated to property, so get_coord
    # and set_coord are called instead
    coord = property(get_coord, set_coord, None, None)

if __name__ == '__main__':
    import doctest
    doctest.testmod()
