Recursive / self-referential parameter? forward reference?

Hello, I am attempting to model a class where a person is sponsored by a person. But since the “person class” (in this case the class is named ‘Marketer’) is not defined, I dont think this will work:

class Marketer(Parameterized):
    id = Number()
    sponsor = Marketer()   ## Troublesome line!!!
    front_line = Number(5)

I think that this works:

import param

class Marketer(param.Parameterized):
    id = param.Number()
    sponsor = Marketer()

Marketer.param.add_parameter('sponsor', param.ClassSelector(class_=Marketer))

m = Marketer(id=1, sponsor=Marketer(id=2))

What do you think @jbednar ?

Why ClassSelector instead of item_type=Marketer?

item_type is a parameter that is only available for the List Parameter, it’s used to make sure that all the items of a list are of the same type. In this case it seems to me that sponsor will not hold a list of objects but a single object, an instance of Marketer, which is what ClassSelector is used for (its parameter is_instance is True by default, so it’ll check that you correctly pass an instance of Marketer).

The pattern we have used in this case before (e.g. in Imagen) is to specialize the type of the ClassSelector immediately after the class is created:

import param

class Marketer(param.Parameterized):
    id = param.Number()
    sponsor = param.ClassSelector(param.Parameterized)
    front_line = param.Number(5)

m = Marketer()
m.sponsor = Marketer(id=7)
m.sponsor = "should raise an exception"

That way the original class definition is as close as possible to what you want, and only the last little bit has to be deferred.

Of course, if you can avoid this by making there be a more general superclass of which Marketer is a subtype and sponsor is an instance, you won’t need to do this.

1 Like