Search code examples
pythonclassoophasattr

Why an object can be split into 2 components


I came across this class Vector2 which was constructed like this

class Vector2:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

        if hasattr(x, "__getitem__"):
            x, y = x
            self._v = [float(x), float(y)]
        else:
            self._v = [float(x), float(y)]

    def __getitem__(self, index):
        return self._v[index]

    def __setitem__(self, index, value):
        self._v[index] = 1.0 * value
        
    def __str__(self):
        return "(%s, %s)"%(self.x, self.y)

As I don't have much knowledge in Python, I couldn't understand the first line of the block if hasattr(x, "__getitem__"):

if hasattr(x, "__getitem__"):
            x, y = x # why can we do this?

I meant how could x be split into x and y because x is already itself (that is, x == x)?

Also, what is the objective/purpose of hasattr(x, "__getitem__")?

EDIT: If I instantiated a vector v1 = Vector2(100, 200) to represent the movement of an object in pygame, I found out that I couldn't use v1[0] to specify the location of the object on the x-axis for drawing (with pygame.blit()). Why was that, given v1[0] == v1.x?

EDIT 2: correction of the edit above. I was wrong, v1[0] (same as v1.x) can be used to specify the location of the object.


Solution

  • I believe the code's author intended to support passing tuples as initial parameters for creating a new object from the class, Vector2.

    The condition if hasattr(x, "__getitem__"): serves as a loose check to verify if the argument passed is a tuple.

    For example if you pass (5, 2) when initializing an object of Vector2 class,

    point = Vector2((5, 2))
    

    the code block, x, y = x will split it and initialize the co-ordinates as x = 5 and y = 2

    Read more about __getitem __