Wait for event to finish before resolving other dependencies

If I have an event that depends on two parameters, which usually (but not always) get updated simultaneously. However, this causes the event to be triggered twice. How can I tell Param to wait for the first event to finish?

For example:

import param

class A(param.Parameterized):

    n = param.Number(1.2)

    x1 = param.Integer(1)
    x2 = param.Integer(2)

    y1 = param.Number(0.5)

    @param.depends("x1", "x2", watch = True)
    def update_y1(self):
        print("- updating y1...")
        self.y1 = self.x1 / self.x2
        print(f"- y1 is now {self.y1}")

    @param.depends("n", watch = True)
    def update_x1_x2(self):
        print("-- updating x1 and x2...")
        x1, x2 = str(self.n).split(".")
        self.x2 = int(x2)
        print(f"-- x1 and x2 are now [{self.x1}, {self.x2}]")
        self.x1 = int(x1)
        print(f"-- x1 and x2 are now [{self.x1}, {self.x2}]")
    
a = A()

Updating n will cause x1 and x2 to be updated, which in turn causes update_y1 to be triggered twice.

a.n = 4.6

>>> -- updating x1 and x2...
>>> - updating y1...
>>> - y1 is now 0.16666666666666666
>>> -- x1 and x2 are now [1, 6]
>>> - updating y1...
>>> - y1 is now 0.6666666666666666
>>> -- x1 and x2 are now [4, 6]

How do I make sure update_y1 gets only triggered once in this case?

You could self.param.update(x1=..., x2=...)

I figured it out while writing the question, so I’ll just post it here for reference. Turns out the lower level .param.watch method has a solution. Rewriting the example using .param.watch instead of pn.depends(...) and adding the queued keyword to True on the update_x1_x2 method solves the problem:

class A(param.Parameterized):

    n = param.Number(1.2)

    x1 = param.Integer(1)
    x2 = param.Integer(2)

    y1 = param.Number(0.5)

    def __init__(self, **params):
        super().__init__(**params)

        self.param.watch(fn=self.update_y1, parameter_names=['x1', 'x2'])
        self.param.watch(fn=self.update_x1_x2, parameter_names=['n'], queued=True)
       
    def update_y1(self, *args, **kwargs):
        print("- updating y1...")
        self.y1 = self.x1 / self.x2
        print(f"- y1 is now {self.y1}")

    def update_x1_x2(self, *args, **kwargs):
        print("-- updating x1 and x2...")
        x1, x2 = str(self.n).split(".")
        self.x2 = int(x2)
        print(f"-- x1 and x2 are now [{self.x1}, {self.x2}]")
        self.x1 = int(x1)
        print(f"-- x1 and x2 are now [{self.x1}, {self.x2}]")
    
a = A()
a.n = 4.6 

>>> -- updating x1 and x2...
>>> -- x1 and x2 are now [1, 6]
>>> -- x1 and x2 are now [4, 6]
>>> - updating y1...
>>> - y1 is now 0.6666666666666666

Ah yes, that’s a lot simpler than my solution, Thanks!