Matplotlib 的 FuncAnimation 多次调用 init_func

Eli*_*hle 4 python animation matplotlib

的文档matplotlib.animation.FuncAnimation说:

init_func : [...] 该函数将在第一帧之前调用一次。

但每当我使用 时FuncAnimation,都会init_func被多次调用。您可以通过向 Matplotlib 网站的基本示例添加打印语句来查看这一点:

"""
A simple example of an animated plot
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()

x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))


def animate(i):
    line.set_ydata(np.sin(x + i/10.0))  # update the data
    return line,


# Init only required for blitting to give a clean slate.
def init():

    # ---> Adding a print statement here <---
    print('Initializing')  

    line.set_ydata(np.ma.array(x, mask=True))
    return line,

ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), init_func=init,
                              interval=25, blit=True)
plt.show()    
Run Code Online (Sandbox Code Playgroud)

除了产生一个可爱的情节之外,它还立即给出标准输出:

Initializing
Initializing
Run Code Online (Sandbox Code Playgroud)

如果我保持动画运行,init_func实际上会一遍又一遍地调用!这是一个错误还是一个功能?我能做什么呢?


一点背景知识:我使用init_func来初始化多个图,如此处所述,仅在一个类中:

class MyAnimation:
    def __init__(self, n):
        self.fig, self.ax = plt.subplots()
        self.n = n
        self.lines = []

    def run_animation(self):
        def init():
            for i in range(self.n):
                line = ax.plot([], [])[0]
                self.lines.append(line)     
            return self.lines

        def animate(i):
            ... # Update lines
            return self.lines

        animation = FuncAnimation(self.fig, animate, init_func=init, blit=True)
        plt.show()       
Run Code Online (Sandbox Code Playgroud)

当然,如果init()多次调用,这是没有意义的,因为额外的行将被附加到self.lines. 我的方法不是很好的做法吗?我应该在函数self.lines = []内部设置吗init()

Imp*_*est 5

首先应该提到的是“该函数将在第一帧之前调用一次”。意味着它在每个动画的第一帧之前调用一次。因此,因为FuncAnimation'srepeat参数是True默认的,每次重复动画时,init_func都会再次调用。

接下来你是对的,这个函数实际上被调用了两次。第一个调用是设置动画。这一步显然是内部需要的。因此,应该考虑到这一点,并确保 init 函数不会在图中产生任何不可逆的东西。
另请注意,如果您未提供任何 init_func,则第一帧将用于内部设置过程。

lines因此,我认为您重置 中的属性是完全正确的init_func。您甚至可能想要清除轴 ( self.ax.clear()) 以删除以前绘制的元素。