Repository: ManimCommunity/manim
File: manim/animation/composition.py (Python)

Code before:
    .. manim:: LaggedStartMapExample

        class LaggedStartMapExample(Scene):
            def construct(self):
                title = Tex("LaggedStartMap").to_edge(UP, buff=LARGE_BUFF)
                dots = VGroup(
                    *[Dot(radius=0.16) for _ in range(35)]
                    ).arrange_in_grid(rows=5, cols=7, buff=MED_LARGE_BUFF)
                self.add(dots, title)

                # Animate yellow ripple effect
                for mob in dots, title:
                    self.play(LaggedStartMap(
                        ApplyMethod, mob,
                        lambda m : (m.set_color, YELLOW),
                        lag_ratio = 0.1,
                        rate_func = there_and_back,
                        run_time = 2
                    ))
    """

    def __init__(
        self,
        AnimationClass: Callable[..., Animation],
        mobject: Mobject,
        arg_creator: Callable[[Mobject], str] | None = None,
        run_time: float = 2,
        **kwargs: Any,
    ):
        args_list: list[str | tuple[Mobject]] = []
        for submob in mobject:
            if arg_creator:
                args_list.append(arg_creator(submob))
            else:
                args_list.append((submob,))
        anim_kwargs = dict(kwargs)
        if "lag_ratio" in anim_kwargs:
            anim_kwargs.pop("lag_ratio")
        animations = [AnimationClass(*args, **anim_kwargs) for args in args_list]
        super().__init__(*animations, run_time=run_time, **kwargs)


Review comment (suggestion):
The docstring contains an example where `arg_creator` returns a tuple of arguments `(m.set_color, YELLOW)`, contradicting the typehint which was written here before. The return type should actually be `Iterable[Any]`, which makes more sense: this function creates the positional arguments which will be passed to the animation.

```suggestion
        arg_creator: Callable[[Mobject], Iterable[Any]] | None = None,
```

Code after:
    .. manim:: LaggedStartMapExample

        class LaggedStartMapExample(Scene):
            def construct(self):
                title = Tex("LaggedStartMap").to_edge(UP, buff=LARGE_BUFF)
                dots = VGroup(
                    *[Dot(radius=0.16) for _ in range(35)]
                    ).arrange_in_grid(rows=5, cols=7, buff=MED_LARGE_BUFF)
                self.add(dots, title)

                # Animate yellow ripple effect
                for mob in dots, title:
                    self.play(LaggedStartMap(
                        ApplyMethod, mob,
                        lambda m : (m.set_color, YELLOW),
                        lag_ratio = 0.1,
                        rate_func = there_and_back,
                        run_time = 2
                    ))
    """

    def __init__(
        self,
        animation_class: type[Animation],
        mobject: Mobject,
        arg_creator: Callable[[Mobject], Iterable[Any]] | None = None,
        run_time: float = 2,
        **kwargs: Any,
    ):
        if arg_creator is None:

            def identity(mob: Mobject) -> Mobject:
                return mob

            arg_creator = identity

        args_list = [arg_creator(submob) for submob in mobject]
        anim_kwargs = dict(kwargs)
        if "lag_ratio" in anim_kwargs:
            anim_kwargs.pop("lag_ratio")
        animations = [animation_class(*args, **anim_kwargs) for args in args_list]
        super().__init__(*animations, run_time=run_time, **kwargs)