pythonpointdimension

Point values not being handled correctly


I have a PointND class representing a point in N-dimensional space (shown below).

class PointND:
    """
    Class to represent an N-dimensional point.
    """
    def __init__(self, *vals):
        if len(vals) == 1 and isinstance(vals, list):
            self.vals = vals[0]
        else:
            self.vals = vals
        self.point = []
        self.dimensions = len(self.vals)
        for i in self.vals:
            self.point.append(i)

This works fine when I give it a series of inputs (ex: PointND(1, 2, 3, 4)). However, whenever I give it a list of inputs (ex: PointND([1, 2, 3, 4])) it breaks.

I have the __repr__ function defined as:

def __repr__(self):
        __a = f"{self.dimensions}D Point: ({self.vals[0]}"
        for i in range(1, len(self.vals)):
            __a = f"{__a}, {self.vals[i]}"
        __a = f"{__a})"
        return __a

And when I do print(PointND(1, 2, 3, 4, 5)), it outputs:

> 4D Point: (1, 2, 3, 4)

However when I simply change it to: print(PointND([1, 2, 3, 4, 5])), it outputs:

> 1D Point: ([1, 2, 3, 4])

I don't know why it does this, but if anyone knows and/or has a fix, please let me know!


Solution

  • Here you probably meant to check the type of vals[0], not vals.

        def __init__(self, *vals):
    -       if len(vals) == 1 and isinstance(vals, list):
    +       if len(vals) == 1 and isinstance(vals[0], list):
                self.vals = vals[0]
            else:
                self.vals = vals
    

    (vals will never be a list, it will always be a tuple)

    I would argue that this is a bad interface: it lets you express the same thing in two different ways. I would pick one way of creating a point:

    # a) accept varargs
        def __init__(self, *vals):
            self.point = list(vals)
            self.dimensions = len(vals)
    
    # b) accept a list (or any iterable, really)
        def __init__(self, vals):
            self.point = list(vals)
            self.dimensions = len(vals)