我正在尝试创建一个动画,我想要一个点和线列表来跟踪一个值。为此,我使用 ValueTracker 对象和更新程序方法。使用 ShowCreation,我已经将这些对象添加到场景中。我使用 for 循环为列表中的每个点和线添加更新程序(两个列表具有相同的长度):
for i in range(len(x_points)):
dots_cos[i].add_updater(
lambda mob: mob.move_to(axes2.c2p(x_points[i], np.cos(omega.get_value()*x_points[i]))),
# call_updater=False
)
dots_sin[i].add_updater(
lambda mob: mob.move_to(axes2.c2p(x_points[i], np.sin(omega.get_value()*x_points[i]))),
# call_updater=False
)
lines_cos[i].add_updater(
lambda mob: mob.become(Line(axes2.coords_to_point(x_points[i], 0),
axes2.coords_to_point(x_points[i], np.cos(omega.get_value()*x_points[i])), color=YELLOW)),
# call_updater=False
)
lines_sin[i].add_updater(
lambda mob: mob.become(Line(axes2.coords_to_point(x_points[i], 0),
axes2.coords_to_point(x_points[i], np.sin(omega.get_value()*x_points[i])), color=RED)),
# call_updater=False
)
这没有按预期工作!发生的情况是,只有相应列表中的最后一个元素获得了更新程序,并且正常工作,而其余元素只是从场景中消失了!我尝试在 zip(x_points, dots_cos, dots_sin, lines_cos, lines_sin)
上运行 for 循环,但结果还是一样。
有趣的是,当我尝试使用 while 循环执行相同操作时,代码尝试将更新程序添加到最后+1 次迭代,而不是循环的最后一次迭代,因此抛出了 IndexOutOfBounds 异常。尽管像 print 语句这样的良性语句在 while 循环中工作得很好。
此外,如果它很重要,则使用返回这些列表的用户定义函数生成点和线列表。
那么这里有什么问题呢? add_updater 函数如何破坏 for 循环这样基本的东西?
最佳答案
您遇到了一个众所周知的循环构造 lambda 问题。您的解决方案可能是:
lambda mob, i=i: ...
关于python - 为什么有些语句仅适用于 manim 中 for 循环的最后一次迭代?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60901675/