from math import sqrt

class Point:
    """n-dimensional point

    coord - list of floats representing coordinates.
    """

    def __init__(self, coord):
        """ (Point, list-of-floats) -> NoneType

        Initialize new point self to have coordinates coord.

        >>> p = Point([3, 4])
        >>> p.coord == [3.0, 4.0]
        True
        """
        # 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

        Return distance from origin to self.

        >>> p = Point([3, 4])
        >>> p.distance()
        5.0
        """
        return ( # parenthesis for grouping across lines
            sum( #the sum of...
                # squares of elements in self.coord
                [x*x for x in self.coord]
            ))**(1/2) # the square root

    def __eq__(self, other):
        """ (Point, object) -> 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 ( # parenthesis for grouping across lines
            isinstance(other, Point) and # make sure other's a Point and
            self.coord == other.coord # check whether coords are equivalent
            )

    def __str__(self):
        """ (Point) -> str

        Return a string version of self.

        >>> p = Point([3, 4])
        >>> print(p)
        (3.0, 4.0)
        """
        return str(tuple(self.coord))

    def __repr__(self):
        """ (Point) -> str

        Return a string representation of self that evaluates
        into an equivalent Point.
        
        >>> p = Point([3, 4])
        >>> p
        Point([3.0, 4.0])
        """
        return "Point({})".format(self.coord)

    def _set_coord(self, coord):
        """ (Point, list-of-floats) -> NoneType

        Set coordinates for self
        """
        if '_coord' in dir(self): # has _coord already been set?
            raise Exception('Cannot reset coords')
        else: # if not already set, go ahead!
            self._coord = tuple(coord)

    def _get_coord(self):
        """ (Point) -> list-of-float

        Return list of coordinates for self
        """
        return list(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()
