在 DynamicModule 中打印动态变量

发布于 2024-12-09 10:44:15 字数 1195 浏览 0 评论 0原文

为什么在下面的示例中,不是 b 的值被打印,而是符号名称?如何强制打印变量的实际动态值?

a = {1, 2, 3};

DynamicModule[{b},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ,
 Initialization :> (b = Length[a]; a = a + 2)
 ]

输出:

b$107

Out[2]= {{3, 4, 5}, 3}

编辑(阅读您的答案/评论后):

考虑更简单的示例,没有初始化代码(以绕过 WReach 的示例):

a = {1, 2, 3};

DynamicModule[{b = Length[a]},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ]

输出:

During evaluation of In[4]:= b$602

Out[5]= {{1, 2, 3}, 3}

请注意,此示例如果我使用 Module 而不是 DynamicModule 或从 Print 行中省略 Dynamic ,则会执行我想要的操作。我的担忧是:

  1. 为什么第二个示例无法正确打印 b 的值?没有初始化,其中(根据帮助)包含“首次显示 DynamicModule 时要计算的表达式”。另根据帮助:“首次评估DynamicModule时,首先对局部变量进行初始赋值,然后评估Initialization选项的任何设置。”

  2. 帮助应为:“初始化:首次显示 DynamicModule结果时计算的表达式”,这意味着 Print屏幕上的语句并不构成DynamicModule的“结果”。如果这是正确的,那么(并且只有这样)我才明白为什么 Print 语句并不意味着 Dynamic 对象正确显示。

Why is it that not the value of b gets printed in the following example but the symbolname? How can I force the printing of the actual dynamic value of the variable?

a = {1, 2, 3};

DynamicModule[{b},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ,
 Initialization :> (b = Length[a]; a = a + 2)
 ]

output:

b$107

Out[2]= {{3, 4, 5}, 3}

Edit (after reading your answers/comments):

Consider the more simple example, without Initialization code (to get around WReach's example):

a = {1, 2, 3};

DynamicModule[{b = Length[a]},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ]

output:

During evaluation of In[4]:= b$602

Out[5]= {{1, 2, 3}, 3}

Note, that this example does what I want to if I use Module instead of DynamicModule or leave out Dynamic from the Print line. My concerns are:

  1. Why does this second example fail to print the value of b correctly? There is no Initialization, which (according to the help) contains "an expression to evaluate when the DynamicModule is first displayed". Also according to help: "When DynamicModule is first evaluated, initial assignments for local variables are made first, and then any setting for the Initialization option is evaluated."

  2. The help should read: "Initialization: an expression to evaluate when the result of DynamicModule is first displayed", meaning that a Print statement onscreen does not constitute the "result" of the DynamicModule. If this is correct, then (and only then) I understand why the Print statement does not mean that the Dynamic object appears correctly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

在风中等你 2024-12-16 10:44:15

我相信发生这种情况是因为调用 Print 语句时尚未显示 Dynamic 对象 b,因此初始化尚未完成制成。我记得,动态功能只有在实际、可见地显示后才会运行。

请参阅 为什么这不起作用?动态选择以获取更多信息。


针对您的更新,我的理论是前端永远不会显示 Print 中的 Dynamic 语句,因此它永远不会真正初始化。也就是说,它仍然是一个唯一的占位符,等待最终显示时由 b 的动态值填充。

从下面的示例中可以看出,分配 RHS 评估发生在正文 Print 之前,至少通过前端中的显示顺序来衡量。此外,我们看到 Print “进入”Dynamic 并获取由 DynamicModule 创建的唯一符号名称,并将其打印出来。我们可以使用 ToString 使 Print 按原样显示整个表达式。同样,如果我们从该字符串中提取符号名称,并将其转换为实际符号,则在打印之前,我们会得到确实已经分配的预期值。

alarm := (Print["Initialized!"]; 3)

DynamicModule[{b = alarm},
  Print @ ToString @ Dynamic @ b;
  Print @ Symbol @ StringTake[ToString@Dynamic@b, {9, -2}];
  Print @ Dynamic @ b;
];

输出:

Initialized!

Dynamic[b$701]

3

b$701 

I believe this happens because the Dynamic object b has not been displayed at the time the Print statement is called, and therefore the initialization has not been made. As I recall, Dynamic functionality does not operate until it is actually, visibly displayed.

See Why won't this work? Dynamic in a Select for more information.


In response to your update, my theory is that the Dynamic statement within Print in never displayed by the FrontEnd, and therefore it is never actually initialized. That is, it remains a unique placeholder, waiting to be filled by the dynamic value of b when it is finally displayed.

One may see from the example below that the assignment RHS evaluation takes place before the body Print, at least by measure of the display order in the FrontEnd. Further, we see that Print "goes inside" Dynamic and takes the unique symbol name created by DynamicModule, and prints that. We can use ToString to cause Print to display the entire expression as it is. Likewise, if we extract the symbol name from that string, and convert it to an actual symbol, before printing, we get the expected value that has indeed already been assigned.

alarm := (Print["Initialized!"]; 3)

DynamicModule[{b = alarm},
  Print @ ToString @ Dynamic @ b;
  Print @ Symbol @ StringTake[ToString@Dynamic@b, {9, -2}];
  Print @ Dynamic @ b;
];

Output:

Initialized!

Dynamic[b$701]

3

b$701 
思慕 2024-12-16 10:44:15

文档的更多信息部分描述了关键行为动态模块

DynamicModule首先为expr中的局部变量提供唯一的名称,
就像 Module 一样,然后计算结果表达式,然后
返回包装在DynamicModule中的版本。

如果您将 Print 语句添加到 Initialization 选项,则事件的确切顺序会变得更加明显,从而:

a = {1, 2, 3};

DynamicModule[{b},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ,
 Initialization :> (b = Length[a]; Print["init:", b]; a = a + 2)
 ]

产生三个单元格:

        b$107

Out[7]= {{3, 4, 5}, 3}

        init:3

包含 b$107 的单元格code> 是 DynamicModulePrint 的结果。然后,我们得到结果单元格(此处标记为 Out[7])。最后,我们看到 InitializationPrint 语句输出的第三个单元格。

如果检查 Out[7] 单元格的单元格表达式,您会发现本地化变量是 b$$。这与第一个单元格中的变量 b$107 不同。这种差异可归因于DynamicModule 文档中描述的“双重作用域”。 b$107 单元格包含一个 Dynamic 框,如果我们为 b$107 赋值,就可以看到。

更新

针对更新后的问题...

返回原始表达式(没有初始化中额外的Print),确切的序列事件如下:

首先,在“为局部变量提供唯一名称[...]就像模块”之后,对DynamicModule的主体进行评估。也就是说,计算此表达式:

Print[Dynamic[b$107]]; {Dynamic[a], Dynamic[b$107]}

此表达式的结果是列表 {Dynamic[a], Dynamic[b$107]}。作为副作用,会创建一个包含 b$107 的动态单元格,但该单元格现在已从进一步考虑中删除,因为它不是评估结果的一部分。现在,“[{Dynamic[a], Dynamic[b$107]}] 的版本被包装在DynamicModule中”并返回。对此进行评估并隐式打印以生成如下输出单元表达式:

Cell[BoxData[
 DynamicModuleBox[{$CellContext`b$ = 3}, 
  RowBox[{"{", 
   RowBox[{
    DynamicBox[ToBoxes[$CellContext`a, StandardForm],
     ImageSizeCache->{57., {2., 8.}}], ",", 
    DynamicBox[ToBoxes[$CellContext`b$, StandardForm],
     ImageSizeCache->{7., {0., 8.}}]}], "}"}],
  DynamicModuleValues:>{},
  Initialization:>($CellContext`b$ = 
    Length[$CellContext`a]; $CellContext`a = $CellContext`a + 2)]], "Output"]

特别注意,b$107 被重命名为 $CellContext`b$$ 作为 的函数DynamicModule 符号本地化。现在,当框显示且可见时,将计算初始化表达式。

关键点是包含 b$107 的打印单元没有以任何方式耦合到最终的DynamicModule 单元。

The crucial behaviour is described under the More Information section of the documentation for DynamicModule:

DynamicModule first gives unique names to local variables in expr,
just like Module, then evaluates the resulting expression, and then
returns a version of this wrapped in DynamicModule.

The exact sequence of events becomes more apparent if you add a Print statement to the Initialization option, thus:

a = {1, 2, 3};

DynamicModule[{b},
 Print[Dynamic[b]];
 {Dynamic[a], Dynamic[b]}
 ,
 Initialization :> (b = Length[a]; Print["init:", b]; a = a + 2)
 ]

resulting in three cells:

        b$107

Out[7]= {{3, 4, 5}, 3}

        init:3

The cell containing b$107 is the result of the Print inside the DynamicModule. Then, we get the result cell (tagged Out[7] here). Finally, we see the third cell output by Print statement in the Initialization.

If you inspect the cell expression of the Out[7] cell, you will find that the localized variable is b$$. This is different from the variable in the first cell, which is b$107. This difference is attributable to the "double scoping" described in the DynamicModule documentation. The b$107 cell contains a Dynamic box, as can be seen if we assign a value to b$107.

Update

In response to the updated question...

Returning to the original expression (without the extra Print in the Initialization), the exact sequence of events is as follows:

First, the body of the DynamicModule is evaluated after giving "unique names to local variables [...] just like Module". That is, this expression is evaluated:

Print[Dynamic[b$107]]; {Dynamic[a], Dynamic[b$107]}

The result of this expression is the list {Dynamic[a], Dynamic[b$107]}. As a side-effect, a dynamic cell containing b$107 is created but that cell is now removed from further consideration as it is not part of the result of the evaluation. Now, "a version of [{Dynamic[a], Dynamic[b$107]}] is wrapped in DynamicModule" and returned. This is evaluated and implicitly printed to produce an output cell expression like this:

Cell[BoxData[
 DynamicModuleBox[{$CellContext`b$ = 3}, 
  RowBox[{"{", 
   RowBox[{
    DynamicBox[ToBoxes[$CellContext`a, StandardForm],
     ImageSizeCache->{57., {2., 8.}}], ",", 
    DynamicBox[ToBoxes[$CellContext`b$, StandardForm],
     ImageSizeCache->{7., {0., 8.}}]}], "}"}],
  DynamicModuleValues:>{},
  Initialization:>($CellContext`b$ = 
    Length[$CellContext`a]; $CellContext`a = $CellContext`a + 2)]], "Output"]

Note particularly that b$107 is renamed to $CellContext`b$$ as a function of DynamicModule symbol localization. The Initialization expression is now evaluated as the box is displayed and visible.

The key point is that the printed cell containing b$107 is not coupled in any way to the final DynamicModule cell.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文