What is the purpose of @param.depends in a parameterized class?

I think the title describes the question - It is not clear why param.depends is actually needed in a parameterized class.

For instance, I can comment @param.depends('phase', 'frequency') out completely in this simple example from the docs, and the plot is still reactive to changes in the widgets.

import numpy as np
class Sine(param.Parameterized):

    phase = param.Number(default=0, bounds=(0, np.pi))

    frequency = param.Number(default=1, bounds=(0.1, 2))

    @param.depends('phase', 'frequency') # This is entirely unnecessary for the app to function
    def view(self):
        y = np.sin(np.linspace(0, np.pi * 3, 40) * self.frequency + self.phase)
        y = ((y - y.min()) / y.ptp()) * 20
        array = np.array(
            [list((' ' * (int(round(d)) - 1) + '*').ljust(20)) for d in y])
        return pn.pane.Str('\n'.join([''.join(r) for r in array.T]), height=380, width=500)

sine = Sine(name='ASCII Sine Wave')
pn.Row(sine.param, sine.view)

To me that is actually surprising. I did not know that a function of parameterized class was reactive to its parameters by default.

My question now is whether @param.depends then can be used to say it’s only depending on a subset of parameters of the Class?

1 Like

Ah yes, that is it. The default behavior is being reactive to everything, and @param.depends can be a limiting feature.

1 Like

I think this is related to the question I asked here: How to set fine grained dependencies when setting options in the viewable function?

The idea is explained in the example here by @jbednar : https://examples.pyviz.org/datashader_dashboard/dashboard.html (check out the bit about fine-grained dependencies). I also implemented something like it here: https://github.com/dhruvbalwada/glider-panel-demo/blob/main/glider_trajectory_plot.ipynb (I think you should be able to run it using the jupyter lab via binder).

From what I understood in the example is that it makes a HUGE difference whether sine.view is passed to the pn.Row or if sine.view() is passed. In the second case the dependencies are not automatically figured out, and things only depends on what the coder specified.

1 Like

That’s correct. The purpose of @param.depends is to declare that the given method depends only on a subset of the parameters. Without any explicit decoration limiting such dependencies, all you know is that every method could depend on any parameter. Presumably with code introspection we could automatically deduce which methods depend on which parameters, but we try not to rely on magic like that, so instead we make the conservative assumption that any change to a parameter could make the output of that method be stale and thus need updating. In practice I’d recommend always declaring the dependencies explicitly for a viewable method so that humans know you meant to depend on those parameters and so that your function won’t be called unnecessarily for unrelated parameter changes.