Param 2.0 release

release
param
Release announcement for Param 2.0
Author

Maxime Liquet

Published

December 22, 2023

TL;DR

We are very happy to announce the release of Param 2.0, a Python library that lets you write classes whose attributes, a.k.a. Parameters, are dynamically validated and whose updates can trigger actions you register. This major release includes:

  • improved inheritance of Parameter attributes, now applying even when the value is None, eliminating a previously very confusing limitation
  • extensive clean up of the Parameterized namespace, with public methods (deprecated for a while) moved to the .param namespace and reduced and consolidated private members
  • introduction of the new allow_refs and nested_refs Parameter attributes to allow linking a Parameter value from a reference (e.g. other Parameter value, param.depends function/method)
  • enhancement of the objects attribute of Selector Parameters, so it’s easier to update/access whether it’s been instantiated from a list or from a dictionary
  • introduction of a rich HTML representation for Parameterized instances and classes, which is automatically displayed in notebooks
  • an [experimental] preview of reactive expressions, which form a new declarative and reactive API for writing dynamic code without needing explicit callbacks or dependency declarations.

🌟 An easy way to support Param is to give it a star on Github! 🌟

Find all the changes brought by Param 2.0 in the release notes and see how to migrate your code from Param 1.x to 2.0 in the upgrade guide.

What is Param?

Param is a Python library that lets you write classes whose parameters, are equipped with metadata and are dynamically validated, which simplifies writing classes with a well-defined and defendable API. Additionally, a parameter can be watched to register a callback that is triggered when the parameter value changes.

Here’s a simple example usage of Param, where we create a User class that inherits from param.Parameterized and declares a couple of parameters, including age that can only be a positive integer. We also declare that the callback method submit_data should be called whenever the value of the three declared parameters is updated.

import param

class User(param.Parameterized):
    age = param.Integer(bounds=(0, None), doc='User age')
    fullname = param.String(doc='User full name', constant=True)
    country = param.Selector(default='en', objects=['en', 'fr', 'de'], doc='User country')

    @param.depends('age', 'fullname', 'country', watch=True)
    def submit_data(self):
        print(f'Submit data: {self.age=}, {self.fullname=}, {self.country=}')

user = User(age=33, fullname='John Doe')
user.age, user.fullname, user.country
(33, 'John Doe', 'en')

An error is raised if we try to set the value of one of these parameters to a value that doesn’t satisfy the parameter definition:

with param.exceptions_summarized():
    user.country = 'es'
ValueError: Selector parameter 'User.country' does not accept 'es'; valid options include: '[en, fr, de]'

When we update the value of the parameters of this instance, the callback submit_data gets automatically called:

user.age += 1
Submit data: self.age=34, self.fullname='John Doe', self.country='en'
user.country = 'fr'
Submit data: self.age=34, self.fullname='John Doe', self.country='fr'

These two features, dynamic parameter validation and and callback handling, makes Param an excellent library for supporting GUI code bases. Param is indeed the backbone of the HoloViz libraries HoloViews and Panel, with its integration in Panel being pushed to the extent that its users can easily convert Param objects into visual components. For instance, we can easily create a form from the user object, and to make it a real application we’d just have to update the callback to send data to an API or a database.

import panel as pn
pn.extension()