Manim中多个ValueTracker返回相同值的问题解决求助
解决Manim中多DecimalNumber同步变化的问题
问题根源是循环中定义的lambda没有正确捕获当前迭代的变量:Python的lambda在定义时不会立即锁定变量值,而是在调用时读取变量的当前状态。循环结束后,所有lambda都会引用循环变量的最后一个值,导致所有DecimalNumber绑定到同一个ValueTracker,从而同步变化。
下面是两种针对性的修正方案:
方案1:给lambda添加默认参数捕获当前ValueTracker
修改第一版代码,在lambda中通过默认参数绑定当前迭代的k,确保每个更新器对应独立的ValueTracker:
all_d, all_t = [], [] for tile in tiles: start_number = random() k = ValueTracker(start_number) # 通过默认参数k=k,捕获当前迭代的ValueTracker实例 updateFunction = lambda i, k=k: i.set_value(k.get_value()) d = DecimalNumber(num_decimal_places=2).add_updater(updateFunction) d.move_to(tile) all_d.append(d) all_t.append(k) print([k.get_value() for k in all_t]) # 输出各ValueTracker的初始随机值 self.play(*[Create(d) for d in all_d]) self.play(*[k.animate.set_value(0) for k in all_t], run_time = 5)
方案2:用functools.partial绑定参数(更清晰)
通过functools.partial显式绑定每个DecimalNumber对应的ValueTracker,避免lambda变量捕获问题:
from functools import partial all_d, all_t = [], [] for tile in tiles: start_number = random() k = ValueTracker(start_number) # 使用partial绑定当前的ValueTracker updateFunction = partial(lambda m, tracker: m.set_value(tracker.get_value()), tracker=k) d = DecimalNumber(num_decimal_places=2).add_updater(updateFunction) d.move_to(tile) all_d.append(d) all_t.append(k) print([k.get_value() for k in all_t]) self.play(*[Create(d) for d in all_d]) self.play(*[k.animate.set_value(0) for k in all_t], run_time = 5)
修正第二版代码的问题
第二版代码同样是lambda捕获索引i的问题,给lambda添加默认参数i=i即可解决:
all_d, all_t = [], [] for i, tile in enumerate(tiles): start_number = random() d = DecimalNumber(num_decimal_places=2) d.move_to(tile) all_d.append((i, d, start_number)) all_t.append(ValueTracker(start_number)) # 通过默认参数i=i捕获当前迭代的索引 self.play( *[all_t[i].animate.set_value(start_number + 1) for i, _, start_number in all_d], *[UpdateFromFunc(d, lambda m, i=i: m.set_value(all_t[i].get_value())) for i, d, _ in all_d], run_time = 5 )
内容的提问来源于stack exchange,提问作者Andrei
相关产品推荐
相关产品推荐

