-
-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add docs around allow_refs feature #862
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's my suggestion for new intro text, including a more descriptive header: Dynamically linking parametersBuilding on the previous discussion about the dual roles of a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand how the example used to demonstrate nested_refs is an example of nesting; I would have expected something more like this: class U(param.Parameterized):
a = param.Number()
class V(param.Parameterized):
b = param.Number(allow_refs=True)
class W(param.Parameterized):
c = param.Number(allow_refs=True, nested_refs=True)
u = U(a=5)
v = V(b=u.param.a)
w = W(c=v.param.b) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what demonstrates nesting, i.e. the references are nested inside some other container: w = W(c=[u1.param.a, u2.param.a]) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Chaining references like you have done doesn't require any special support. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -784,6 +784,156 @@ | |
"This approach can provide significant speedup and memory savings in certain cases, but should only be used for good reasons, since it can cause confusion for any code expecting instances to be independent as they have been declared." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "2579c782-8dfd-4ded-995f-dc8498f4d275", | ||
"metadata": {}, | ||
"source": [ | ||
"## Parameter references\n", | ||
"\n", | ||
"Having looked at the difference between the `Parameter` value and the `Parameter` object let us consider the idea that a `Parameter` is a reference or proxy for its underlying value. Parameters may be declared to `allow_refs` which effectively means that they will accept other Parameter **objects** (and other valid references) and resolve and reflect their current values." | ||
philippjfr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "111e4911-4b73-40c3-ab57-70cd42eb7fb8", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"class U(param.Parameterized):\n", | ||
" \n", | ||
" a = param.Number()\n", | ||
" \n", | ||
"class V(param.Parameterized):\n", | ||
" \n", | ||
" b = param.Number(allow_refs=True)\n", | ||
" \n", | ||
"u = U(a=3.14)\n", | ||
"v = V(b=u.param.a)\n", | ||
"\n", | ||
"v.b" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "324475cf-65a3-4902-8508-57af19697b5f", | ||
"metadata": {}, | ||
"source": [ | ||
"By declaring that `V.b` allows references we have made it possible to pass the Parameter `U.b`, which means `v.b` will reflect the value of `u.a`:" | ||
philippjfr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "62016252-5a7d-4bb7-be7a-029ed1a47025", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"u.a = 1.57\n", | ||
"\n", | ||
"v.b" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "c6f62936-89bb-49e3-b197-cef43891b2f7", | ||
"metadata": {}, | ||
"source": [ | ||
"This unidirectional link will be in effect until something else tries to set the value:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "28094868-4f23-4399-be7b-da0c73854be7", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"v.b = 14.1\n", | ||
"u.a = 13.2\n", | ||
"\n", | ||
"v.b" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "48878238-e062-4fd4-bb99-0e9020d9b26f", | ||
"metadata": {}, | ||
"source": [ | ||
"In other words, if the value is overridden from the outside the link will be automatically removed.\n", | ||
"\n", | ||
"Simple references are resolved when `allow_refs=True` but to allow nested references we separately have to set `nested_refs=True`." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "d63d949d-79a2-471f-b0bb-232086e486bf", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"class W(V):\n", | ||
" \n", | ||
" c = param.List(allow_refs=True, nested_refs=True)\n", | ||
" \n", | ||
"u1 = U(a=3)\n", | ||
"u2 = U(a=13)\n", | ||
"\n", | ||
"w = W(c=[u1.param.a, u2.param.a]) \n", | ||
"\n", | ||
"w.c" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "e7b3489f-4a75-4767-a7d2-b7066a976ce4", | ||
"metadata": {}, | ||
"source": [ | ||
"When we modify either `u1.a` or `u2.a`, `w.c` will update:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "c2d9fc30-d5cb-49ac-aaf7-d4d6f1d74cb0", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"u1.a = 7\n", | ||
"\n", | ||
"w.c" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "ae2d21b3-c78b-4648-8622-282c237a1d64", | ||
"metadata": {}, | ||
"source": [ | ||
"Note that `Parameter` types are not the only types of valid references. The full list of valid references include:\n", | ||
"\n", | ||
"- Class and instance `Parameter` objects\n", | ||
"- Functions or methods annotated with `param.depends`\n", | ||
"- Functions wrapped with `param.bind`\n", | ||
"- Reactive expressions declared using `param.rx`\n", | ||
"- Asynchronous generators\n", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Allowing bare asynchronous generators isn't going to cause problems with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is going to cause problems if you enable There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The deeper point though is that currently we don't have a way to allow some reference types and not others, which I guess is a problem. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The trick I originally used in Panel was that I would first check if a value would pass There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not currently, but Jim strongly suggested it should be. |
||
"- Custom objects transformed into a valid reference with a hook registered with `param.parameterized.register_reference_transform`.\n", | ||
maximlt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"\n", | ||
"There are two utility functions which allow resolving the value of a reference and all parameters the reference depends on:" | ||
philippjfr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "8cb30e85-5cfe-49d6-a641-f98c84a7acb2", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from param.parameterized import resolve_ref, resolve_value\n", | ||
philippjfr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"\n", | ||
"resolve_ref(u1.param.a), resolve_value(u1.param.a)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "678b7a0e", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
b2.p
is set?b2 = B(p=b1.param.p)
ifallow_refs
was False? Why?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion for new intro text:
Beyond the custom attribute access mechanisms of a single
Parameter
, Param can link together multiple Parameters. With theallow_refs
option, aParameter
can act as a dynamic reference to anotherParameter
. This enables the values of two or more Parameters to stay in sync, allowing for reactive development. Any change to the referenced Parameter's value is automatically reflected in all Parameters that reference it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@philippjfr what is your take on bi-directionally linking Parameters in Param? I'd guess there's a way for this to be implemented, if so let's open an issue to discuss the API? I'd love Param 2.1 to have it to be able to deprecate Panel's
.link
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, would like to see the same.