Hey @Marc, thanks for your answer. Here is my minimum reproducible example, and the solution I’ve just tested based on your answer.
The guys I work with have a class that they have developed, on the hardware side of things. This is working for them, but we’re moving to displaying data, so that’s why I’m testing Panel. The class they have is, simplifying a lot, this one:
class Sensor():
def __init__(self, sensorID, status):
self.sensorID = sensorID
self.status = status
Then they have some properties that get a stream directly from the hardware and update that status (and shows it on the device, on a screen). I can’t touch this code, as it’s already in production.
Now that we’re moving to dashboards, this status needs to be displayed. I was kind of stumped by trying multiple things, but the solution inspired by your post, the response I got on twitter and diving through the docs is this one: instead of getting the instances they make, I derive the class and parametrize it.
#Subclassing and parametrizing the status
class DerivedSensor(Sensor, param.Parameterized):
status = param.Parameter()
test_sensor = DerivedSensor('test', 1) # Instantiate the derived class with the parent's init
number = pn.indicators.Number(
name=test_sensor.sensorID + ' Status', value=test_sensor.status,
colors=[(0, 'green'), (1, 'orange'), (9, 'orange'), (10000, 'red')]
)
# Now we rely on the "links" tutorial from panel's doc
def callback(event):
if event.name == 'status':
number.value = event.new
#last, define the watcher and show the number
watcher = test_sensor.param.watch(callback, ['status'])
number.show(threaded=True)
This works, and the number now is able to update whenever I modify it on console (akin to what the actual Sensor class does).
The thing that seems weird about this to me is that when I subclass Sensor, I’m defining “status” as a parameter. But then when I instantiate it, I “overwrite”, setting it to whatever I want, instead of using the param library, but it keeps working. If I check its type, it’s whatever I set it too (int if I throw an int at it, float if I throw a float), when I would expect a param type.
I don’t know if this is the intended use of the param library (I tried to look for examples, but they were a bit sparse, focusing on what’s likely the usual way of using the library (defining the class with param use in mind). Also, I’m probably a bit in over my head, as a couple of months ago I basically didn’t know what objects where, only having ever used functional programming, much like I would on my Uni Matlab classes.
IDK, maybe this is the right way to do these things, and it just seems convoluted to me because of lack of OOP experience. If anyone has a simpler way that would be great, but in the end, this works, and coupling the callback definition with the Number definition can make this really scalable.
Thanks for your help!