Wanting to update a list attribute in a class without having to call an update function for every change

Viewed 182

This is what I'm working with:

class Vector:
    def __init__(self):
        self.x = 0
        self.y = 0
        self.z = 0
        self.w = 0
        self.data = [
            [self.x],
            [self.y],
            [self.z],
            [self.w]
        ]

Is it possible to update self.data any time another attribute changes? I know I could just write an update function for it like:

def update(self):
        self.data = [
            [self.x],
            [self.y],
            [self.z],
            [self.w]
            ]

but I would rather not call v.update() 60 times/second.

I also know that I could just not use other attributes and update the list indices by doing v.data[0] = 5, but it would be nice to do v.x = 5 for readability (v is an instance of Vector).

For now I'm just biting the v.data[0] = 5 bullet...

Edit: Data is a list of lists for matrix multiplication.

2 Answers

You can create your own objects for x, y, z, and w that have a custom update method. That way, when ever those attributes are updated, the change will be reflected via reference in data:

class Component:
   def __init__(self, val = 0, name='x'):
      self.val, self.name = val, name
   def update(self, new_val):
      self.val = new_val
   def __repr__(self):
      return f'{self.name}({self.val})'

class Vector:
   def __init__(self):
      self.x = Component(name='x')
      self.y = Component(name='y')
      self.z = Component(name='z')
      self.w = Component(name='w')
      self.data = [
        [self.x],
        [self.y],
        [self.z],
        [self.w]
      ]

v = Vector()
print('before update: ', v.data)
v.x.update(100)
v.y.update(200)
v.z.update(300)
v.w.update(400)
print('after update: ', v.data)

Output:

before update:  [[x(0)], [y(0)], [z(0)], [w(0)]]
after update:  [[x(100)], [y(200)], [z(300)], [w(400)]]

You could use a single place to store the data and make the x,y,z,w peoperties that read and write self.data at their respective indexes:

class Vector:
    
    def dataProperty(i):
        def getter(obj): return obj.data[i][0]
        def setter(obj,value): obj.data[i][0] = value
        return property(getter,setter)

    x,y,z,w = map(dataProperty,range(4))
    
    def __init__(self):
        self.data = [[0] for _ in range(4)]

output:

v = Vector()
v.x = 123
v.z = 456

print(v.data) # [[123], [0], [456], [0]]

v.data[0][0] += 876

print(v.x) # 999
Related