BTW, here’s how I’d translate the pydantic home page example into Param:
import param
class User(param.Parameterized):
id = param.Integer()
name = param.String()
signup_ts = param.Date(None)
friends = param.List([], item_type=int)
from datetime import datetime
external_data = {
'id': 123,
'name': 'John Doe',
'signup_ts': datetime.strptime('2019-06-01 12:22', '%Y-%m-%d %H:%M'),
'friends': [1, 2, 3],
}
user = User(**external_data)
print(user.id)
#> 123
print(repr(user.signup_ts))
#> datetime.datetime(2019, 6, 1, 12, 22)
print(user.friends)
#> [1, 2, 3]
print(user.param.values())
"""
{
'friends': [1, 2, 3],
'id': 123,
'name': 'John Doe',
'signup_ts': datetime.datetime(2019, 6, 1, 12, 22)
}
"""
This is essentially a direct translation, with some very specific differences:
- Param won’t coerce any foreign type into the required type. So if
idis an integer field, Param will raise an exception (by design) forid='123', while Pydantic accepts that and coerces the string to an int. - Same goes for items in lists; Param will raise “TypeError: List parameter ‘friends’ items must be instances of type <class ‘int’>” if you try supplying
friends= [1, 2, '3'], while Pydantic will coerce it. - A param.Date Parameter will only accept date or datetimes, not strings. Given how painful it is to construct date and datetime objects, I’d be happy to support the specific case of accepting string specifications for Date and CalendarDate constructors, where the string is unlikely to be an error as it would be for the int or list of int cases (as proposed in https://github.com/holoviz/param/issues/580#issuecomment-995094791). In the meantime, it’s necessary for the user to construct the date/datetime object, not Param.
-
nameis the one Parameter that Parameterized objects always have, and it’s also the only one that has special semantics in Param: If the name is not set on an instance or in its constructor, it has a name autogenerated for it from the class name. The intention of this mechanism is for each object to have some relatively unique name to distinguish it when exploring collections of objects, though that’s not necessarily always useful. In any case, here, if we want it to have the valueJohn Doeas in the Pydantic example, we have to provide that name explicitly on the instance as above. The original Pydantic example doesn’t make a whole lot of sense fornameanyway, as it would be a recipe for errors for something like anameto inherit a concrete value likeJohn Doefrom the base class.
I’d be happy to have this example in the docs or the Comparisons page to clarify how Param and Pydantic relate; PRs welcome!