Problem creating constant parameters with dependencies on mutable parameters

Hi all,

New to param/holoviz.

When I attempt to create a constant parameter whose value depends on another mutable parameter, there is unexpected behavior when watch=True - the parameter which should be constant is actually mutable after instantiating the Parameterized class. A simple example:

import param
from deep_translator import GoogleTranslator

class Phrase(param.Parameterized):
    english = param.String(default='Hello')
    french = param.String(constant=True)

    @param.depends('english', watch=True, on_init=True)
    def _translate(self):
        with param.edit_constant(self):
            self.french = GoogleTranslator(source='en', target='fr').translate(self.english)


phrase = Phrase()
print(phrase.french) #'Bonjour'
print(phrase.param.french.constant) #False

#Confirming behavior
phrase.french = 'Goodbye'
print(phrase.english, phrase.french, sep=' -> ') #'Hello -> Goodbye'
phrase.english = 'How are you?'
print(phrase.english, phrase.french, sep=' -> ') #'How are you? -> Comment vas-tu?'

The workaround I found it to set up your class like this:

class Phrase(param.Parameterized):
    english = param.String(default='Hello')
    french = param.String()

    def __init__(self, **params):
        super().__init__(**params)
        self.param.french.constant = True
    ....

#Instance has desired behavior
phrase = Phrase()
print(phrase.french) #'Bonjour'
print(phrase.param.french.constant) #True
phrase.french = 'Goodbye' #Raises TypeError: : Constant parameter 'french' cannot be modified
phrase.english = 'How are you?'
print(phrase.english, phrase.french, sep=' -> ') #'How are you? -> Comment vas-tu?'

While the above works, it gets messy quickly when there are more dependent constants in your class, especially if you are adding even more functionality to your init method.

This dependent constant pattern would be useful, e.g., in complex dashboards where the core data is transformed and the user wants to interface with the transformed data (without allowing ‘fake’ transformed data to creep into the model). Clearly you can do this with more code, but what I really like about param is that allows you to succinctly establish these relationships, and the workaround feels antithetical to the project.

Is there something obvious I’m overlooking? Or has anyone found a cleaner way to implement behavior like this?

Thank you in advance :slight_smile:

Hi, just wanted to share a bug in edit_constant was recently fixed in Param (see Ensure edit_constant resets class and instance level parameters by maximlt · Pull Request #1015 · holoviz/param · GitHub) but not yet released. I’m planning a release at the end of June.

2 Likes

Thanks so much!