Open maximlt opened 4 months ago
Some of the arguments for deprecating pn.interact
.
pn.interact
?pn.interact
seems simple and easy to use when looking at a working example. In practice its often not that simple and easy to use.pn.interact
anyway.Would it make sense to make pn.Param
wrap this or pn.ParamFunction
?
Would it make sense to make pn.Param wrap this or pn.ParamFunction?
Could you explain what you're suggesting.
Functionality of pn.interact migrated to pn.Param
so you can pass Param classes, Python functions (where the params are auto determined by type and positional args), widgets, etc.
import panel as pn
pn.extension()
button = pn.widgets.Button(name='Click me')
def a_function(x: int, y: int, z:int = 10):
return x + y + z
pn.Param([a_function, button], parameters=["x", "y", "clicks"], show_name=False)
Or, on second thought, I don't really know what combining multiple objects will do, so actually maybe not combining them, but just be able to wrap a function.
import panel as pn
pn.extension()
def a_function(x: int, y: int, z:int = 10):
return x + y + z
pn.Param(a_function, parameters=["x", "y"], show_name=False)
Thanks for making that proposal explicit. That said, I'm -100 on overloading pn.Param
like that 😃
Sorry I guess I should have considered ParamFunction too. There I could sort of see it but still think it could be quite unexpected.
For what it's worth, I find Maxim's alternative with pn.bind easier to understand than the pn.interact code. I guess it is less elegant and more verbose though.
For completeness, we discussed two other alternatives. Possible today (though untested):
from panel.widgets.widget import widget as w
widgets = dict(a=w(1.9), b=w(1.9), c=w(1.9), d=w(0.8),
n=pn.widgets.IntSlider(default=1000000, range=(1,20000000)),
colormap=w(ps['kbc']))
pn.bind(clifford_plot, **widgets)
(shorter than explicitly listing all widgets, but more mysterious, and requires a lot of explanation). Or, if we add a function to inspect the function signature the way interact does, but use bind (or .rx):
widgets = pn.widgets(clifford_plot, n=(1,20000000), colormap=ps)
pn.Column(pn.bind(clifford_plot, **widgets), widgets)
Still pretty obscure, and not easy to see how to motify it, but at least avoids adding a fundamentally new API like interact.
I guess one final option: keep interact, but explicitly turn it into a macro, built up out of other calls like shown here. Then if we introduce it, we can say that it's nothing special, just a handy wrapper that's useful in a notebook or command line. Today we can't say that, but I don't think it's a major job to rewrite it using separate functions for synthesizing widgets from values (already useful for pn.rx) plus pn.bind or pn.rx. That might be my vote unless someone comes up with something better!
Hm. I don't have a complete picture of this, but from my perspective, there are already so many parts to Panel that soft-deprecating something (in combination with the macro approach?) seems to be a positive thing. As long as there are good alternatives of course.
Definitely. I think we all agree that we don't think pn.interact fits in, and we do want to reduce the visible API surface of panel, particularly for new users. But we don't seem to have come up with a very good alternative to pn.interact. :-(
@Azaya89 has been working on modernizing the Attractors example on examples.holoviz.org. One of its notebooks makes use of
pn.interact
.pn.interact
has been soft-deprecated in Panel:pn.interact
you can still find the How-Tos that described it and the API referenceI wanted to start a discussion to see:
pn.interact
should really be deprecated,The work done by @Azaya89 has forced us to think about how to replace
pn.interact
with other Panel constructs. The example starts by defining the function that is meant to be interacted with and a dictps
of colormaps meant to be passed to the function.And it just calls
pn.interact
.Which immediately generates this app:
The suggested alternative implementation to
pn.interact(...)
is as follows.With this approach, the widgets must all explicitly be defined,
pn.bind
is used to create a bound function, andpn.Column
is used to layout the widgets and the output of the bound function.While this isn't too complicated Panel code, I think it's still a pretty big gap for users who aren't too familiar with Panel or with Python in general, users that could easily get started with
pn.interact
. To understand/read the code above they need to know about:pn.bind
(binding a function is quite an abstract term, and its similarity withfunctools.partial
won't help the non-advanced Python user).values()
methodOf course, the dictionary creation and unpacking could be replaced by a more explicit and simpler approach, at the expense of making the code longer.
So I wonder:
ipywidgets.interact
or the slightly more complex but more powerful constructs Panel offers.pn.rx
the more natural replacement forpn.interact
? The example could be written without having to create any intermediate variablepn.rx(clifford_plot)(a=pn.widgets.FloatSlider(...), ...)
pn.interact
does? When usinghvplot.interactive
I have sometimes wanted a simpler way to declare a widget compared to the more explicit but longer to typepn.widgets.<Type>(**w_args)
. PerhapsWidget(<value_supported_by_interact>, name=...)
. cc @jbednar who I think has already asked for something like this.