EN VI

Python - How do I call a specific function when a class variable changes?

2024-03-17 21:00:07
Python - How do I call a specific function when a class variable changes?

I've created a class and initialized three variables a, b and c. Now I want to call a specific function func1 whenever the variables a or c are changed from the outside, and a function func2 when variable b is changed from the outside.

I am aware that this can be done using decorators, like this:

class Event:
    def __init__(self, a, b, c):
        self._a = a
        self._b = b
        self._c = c

    @property
    def a(self):
        return self._a
    @a.setter
    def a(self, value):
        self._a = value
        print("Variable a changed!")
        self.func1()

    @property
    def b(self):
        return self._b
    @b.setter
    def b(self, value):
        self._b = value
        print("Variable b changed!")
        self.func2()

    @property
    def c(self):
        return self._c
    @c.setter
    def c(self, value):
        self._c = value
        print("Variable c changed!")
        self.func1()

    def func1(self):
        print("Function 1 called")
    def func2(self):
        print("Function 2 called")

obj = Event(1, 2, 3)
obj.a = 15
obj.b = 10
obj.c = 5

My final code will have 8 or more variables however, and writing a designated @property and @var.setter for every single one of them will be very cumbersome and not really readable.

Is there a simpler way to just say If variables a, c, f, ... are updated, call function X, if b, e, ... are updated, call function Y?

Thank you!

Solution:

You could subclass property with custom features. Here a basic example on how to do that. Notice you should provide a dictionary which maps which property triggers which function (as string).

class TriggerProperty(property):

    MAPPER = {'a': 'func1', 'b': 'func2', 'c': 'func1'}
    
    def __set__(self, obj, value):
        super().__set__(obj, value)
        func_name = self.MAPPER.get(self.fget.__name__)
        getattr(obj, func_name)()


class Event:
    # ...
    @TriggerProperty
    def a(self):
        return self._a

    @a.setter
    def a(self, value):
        self._a = value
        print("Variable a changed!")

    # ...
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login