class_docstr: A mixin class to provide an interface for registering and
  triggering callbacks.
class_docstr_tok: ["A","mixin","class","to","provide","an","interface","for","registering","and","triggering","callbacks","."]
docstr: Add a callback on this object to trigger when ``attr`` changes.
  
  Args:
      attr (str) : an attribute name on this object
      callback (callable) : a callback function to register
  
  Returns:
      None
docstr_tok: ["Add","a","callback","on","this","object","to","trigger","when","``","attr","``","changes",".","Args",":","attr","(","str",")",":","an","attribute","name","on","this","object","callback","(","callable",")",":","a","callback","function","to","register","Returns",":","None"]
code: def on_change(self, attr: str, *callbacks: PropertyCallback) -> None:
      """Add a callback on this object to trigger when ``attr`` changes.
  
      Args:
          attr (str) : an attribute name on this object
          callback (callable) : a callback function to register
  
      Returns:
          None
  
      """
      if len(callbacks) == 0:
          raise ValueError(
              "on_change takes an attribute name and one or more callbacks, got only one parameter"
          )
  
      _callbacks = self._callbacks.setdefault(attr, [])
      for callback in callbacks:
          if callback in _callbacks:
              continue
  
          _check_callback(callback, ("attr", "old", "new"))
          _callbacks.append(callback)
  
file_path: bokeh/src/bokeh/util/callback_manager.py
imports: from __future__ import annotations
  import logging
  from collections import defaultdict
  from inspect import signature
  from typing import TYPE_CHECKING, Any, Callable, Sequence, Union, cast
  from ..events import Event, ModelEvent
  from ..util.functions import get_param_info
label_desc: Use image node_id 2 for calling the PropertyCallbackManager obj's underlying member method code with example usage: obj.on_change(attr) without return types