Parametrisierung#

Panel unterstützt die Verwendung von Parametern und Abhängigkeiten zwischen Parametern, die von param in einfacher Weise ausgedrückt werden, um Dashboards als deklarative, eigenständige Klassen zu kapseln.

Parameter sind Python-Attribute, die mithilfe der param-Bibliothek erweitert wurden, um Typen, Bereiche und Dokumentation zu unterstützen. Dabei handelt es sich lediglich um die Informationen, die ihr zum automatischen Erstellen von Widgets für jeden Parameter benötigt.

Parameter und Widgets#

Hierfür werden zuerst einige parametrisierte Klassen mit verschiedenen Parametern deklariert:

[1]:
import param
import datetime as dt

class BaseClass(param.Parameterized):
    x                       = param.Parameter(default=3.14,doc="X position")
    y                       = param.Parameter(default="Not editable",constant=True)
    string_value            = param.String(default="str",doc="A string")
    num_int                 = param.Integer(50000,bounds=(-200,100000))
    unbounded_int           = param.Integer(23)
    float_with_hard_bounds  = param.Number(8.2,bounds=(7.5,10))
    float_with_soft_bounds  = param.Number(0.5,bounds=(0,None),softbounds=(0,2))
    unbounded_float         = param.Number(30.01,precedence=0)
    hidden_parameter        = param.Number(2.718,precedence=-1)
    integer_range           = param.Range(default=(3,7),bounds=(0, 10))
    float_range             = param.Range(default=(0,1.57),bounds=(0, 3.145))
    dictionary              = param.Dict(default={"a":2, "b":9})

class Example(BaseClass):
    """An example Parameterized class"""
    timestamps = []

    boolean                 = param.Boolean(True, doc="A sample Boolean parameter")
    color                   = param.Color(default='#FFFFFF')
    date                    = param.Date(dt.datetime(2017, 1, 1),
                                         bounds=(dt.datetime(2017, 1, 1), dt.datetime(2017, 2, 1)))
    select_string           = param.ObjectSelector(default="yellow",objects=["red","yellow","green"])
    select_fn               = param.ObjectSelector(default=list,objects=[list,set,dict])
    int_list                = param.ListSelector(default=[3,5], objects=[1,3,5,7,9],precedence=0.5)
    single_file             = param.FileSelector(path='../../*/*.py*',precedence=0.5)
    multiple_files          = param.MultiFileSelector(path='../../*/*.py?',precedence=0.5)
    record_timestamp        = param.Action(lambda x: x.timestamps.append(dt.datetime.now()),
                                           doc="""Record timestamp.""",precedence=0.7)

Example.num_int
[1]:
50000

Wie ihr seht, hängt die Deklaration von Parametern nur von der separaten param-Bibliothek ab. Parameter sind eine einfache Idee mit einigen Eigenschaften, die für die Erstellung von sauberem, verwendbarem Code entscheidend sind:

  • Die param-Bibliothek ist in reinem Python ohne Abhängigkeiten geschrieben, wodurch es einfach ist, sie in jeden Code einzubinden, ohne sie an eine bestimmte GUI- oder Widgets-Bibliothek oder an Jupyter-Notebooks zu binden.

  • Parameterdeklarationen konzentrieren sich auf semantische Informationen, die für eure Domäne relevant sind. So vermeidet ihr, dass domänenspezifischer Code durch irgendetwas verunreinigt wird, das ihn an eine bestimmte Art der Anzeige oder Interaktion mit ihm bindet.

  • Parameter können überall dort definiert werden, wo sie in eurer Vererbungshierarchie sinnvoll sind, und ihr könnt sie einmal dokumentieren, eingeben und auf einen bestimmten Bereich beschränken. Dabei werden alle diese Eigenschaften von einer beliebigen Basisklasse geerbt. Beispielsweise funktionieren hier alle Parameter gleich, unabhängig davon, ob sie in BaseClass oder Example deklariert wurden. Dies erleichtert die einmalige Bereitstellung dieser Metadaten und verhindert, dass sie überall im Code dupliziert werden, wo Bereiche oder Typen überprüft oder Dokumentationen gespeichert werden müssen.

Wenn ihr euch dann für die Verwendung dieser parametrisierten Klassen in einer Notebook- oder Webserverumgebung entscheidet, könnt ihr mit import panel die Parameterwerte als optionalen zusätzlichen Schritt einfach anzeigen und bearbeiten:

[2]:
import panel as pn

pn.extension()

base = BaseClass()
pn.Row(Example.param, base.param)