Combining pn.interact with param.Parameterized?

What is the most convenient equivalent of passing an object as if it were a group of widgets to pn.interact?


class Group(param.parameterized):
   x = param.Integer(10)
   y = param.Integer(20)

# not a method of Group but a function that gets a Group instance
def f(g):
   print(g.x + g.y)

pn.interact(f, g=widget_for_G)

From the documentation I see that something could be done by subclassing G and adding a method that uses G’s fields, in order to decouple computations that may depend on other classes too from G itself. Is there a cleaner way?

Answering my question after playing a bit more, it can be done by using a method on a separate class both using inheritance and composition. The latter is more verbose but actually better fit for my use case where several components are being combined when computation happens.

class X(param.Parameterized):
   x = param.Integer(10)

class Y(param.Parameterized):
   y = param.Integer(20)

class Inherit(X, Y):
    def compute(self):
        return(f"Inherit: {self.x}, {self.y}")

class Compose(param.Parameterized):
    cx = param.ClassSelector(class_=X)
    cy = param.ClassSelector(class_=Y)
    def __init__(self, cx, cy): = cx = cy
    @param.depends('cx.x', 'cy.y')    
    def compute(self):
        return(f"Compose: {}, {}")

c = Compose(X(), Y())
i = Inherit()

    pn.Column(,, c.compute),
    pn.Column(i.param, i.compute)

A third way using ObjectSelector.

xs = [X(x=4), X(x=6)]
ys = [Y(y=10), Y(y=20), Y(y=40)]

class Pick(param.Parameterized):
    cx = param.ObjectSelector(objects=xs, default=xs[0])
    cy = param.ObjectSelector(objects=ys, default=ys[0])
    @param.depends('cx', 'cy', 'cx.x', 'cy.y')
    def compute(self):
        return(f"Pick: {}, {}")

p = Pick()
pn.Column(p.param, p.compute)