Cryptic error message on using parameterized class in Panel

Forgetting to call super.init(**kwargs) in a parameterized Class constructor with its own custom keyword args defined puts out this cryptic message

AttributeError: 'TestStreamParam' object has no attribute '_param_watchers'

Should i open this issue in param or panel ?

Without a minimum reproducible example it’s hard to be sure we understand the issue. Could you post one? Thanks.

1 Like

I got distracted. Here is a minimal failing example

import param
import panel as pn

class TestParam(param.Parameterized):
    onoff = param.Boolean()
    def __init__(self, initial=False):
        onoff = initial
        
    def view(self):
        print(self.onoff)

Using it like this gives the error

tp = TestParam()
pn.Row(tp.param)

The fix is quite simple, Just add **kwargs to the init method and call the super

class TestParam(param.Parameterized):
    onoff = param.Boolean()
    def __init__(self, initial=False, **kwargs):
        super().__init__(**kwargs)
        onoff = initial
....
1 Like

Hi @dwr-psandhu

This is a fantastic, reference example for the community. Thanks

I don’t always provide an example either when I’m distracted or very busy. But I just know that I will probably not get any help because it can be very difficult being on the other end understand the specifics of the question or just time consuming to create a replication example. :slight_smile:

Regarding the question.Yes it’s by design that you need to provide super().__init__. No need for a Github issue.

It is what makes all the functionality of a Parameterized class work. But the first time you miss providing it, it can be troublesome understanding what is wrong. And it is also appears as empty boilerplate to you in this case. On the other hand it gives you the super power to provide or transform the kwargs before __init__.

2 Likes

Better error messages would probably be good in case you forget the super().__init__(), so param issue might still be good.

3 Likes

Thanks @Marc and @philippjfr. I’ll open an issue in param :slight_smile:

1 Like

Hi. I’m new to Param and struggling to understand the behavior of the given example.

import param

class TestParam(param.Parameterized):
    onoff = param.Boolean()
    def __init__(self, initial=False, **kwargs):
        super().__init__(**kwargs)
        onoff = initial

tp = TestParam()
print(tp.onoff) # produces False, correct

tp = TestParam(initial=True)
print(tp.onoff) # produces False, incorrect

The code produces the param.Boolean default value False, no matter the setting of initial:

False
False

Setting onoff=initial, or onoff=True, appears to do nothing, and False is always set.

What am I missing?

Not related to this issue, however you need

self.onoff = initial 
2 Likes