Skip to content

Commit

Permalink
Merge pull request #24337 from meeseeksmachine/auto-backport-of-pr-24…
Browse files Browse the repository at this point in the history
…238-on-v3.6.x

Backport PR #24238 on branch v3.6.x (Update example and docstring to encourage the use of functools.partial in FuncAnimation)
  • Loading branch information
timhoffm committed Nov 1, 2022
2 parents a55a2d6 + 290eec7 commit 8e3f120
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 5 deletions.
34 changes: 31 additions & 3 deletions doc/api/animation_api.rst
Expand Up @@ -108,7 +108,7 @@ this means that the callable objects you pass in must know what
artists they should be working on. There are several approaches to
handling this, of varying complexity and encapsulation. The simplest
approach, which works quite well in the case of a script, is to define the
artist at a global scope and let Python sort things out. For example ::
artist at a global scope and let Python sort things out. For example::

import numpy as np
import matplotlib.pyplot as plt
Expand All @@ -133,8 +133,36 @@ artist at a global scope and let Python sort things out. For example ::
init_func=init, blit=True)
plt.show()

The second method is to use `functools.partial` to 'bind' artists to
function. A third method is to use closures to build up the required
The second method is to use `functools.partial` to pass arguments to the
function::

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from functools import partial

fig, ax = plt.subplots()
line1, = ax.plot([], [], 'ro')

def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return line1,

def update(frame, ln, x, y):
x.append(frame)
y.append(np.sin(frame))
ln.set_data(x, y)
return ln,

ani = FuncAnimation(
fig, partial(update, ln=line1, x=[], y=[]),
frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=True)

plt.show()

A third method is to use closures to build up the required
artists and functions. A fourth method is to create a class.

Examples
Expand Down
17 changes: 15 additions & 2 deletions lib/matplotlib/animation.py
Expand Up @@ -1520,12 +1520,24 @@ class FuncAnimation(TimedAnimation):
func : callable
The function to call at each frame. The first argument will
be the next value in *frames*. Any additional positional
arguments can be supplied via the *fargs* parameter.
arguments can be supplied using `functools.partial` or via the *fargs*
parameter.
The required signature is::
def func(frame, *fargs) -> iterable_of_artists
It is often more convenient to provide the arguments using
`functools.partial`. In this way it is also possible to pass keyword
arguments. To pass a function with both positional and keyword
arguments, set all arguments as keyword arguments, just leaving the
*frame* argument unset::
def func(frame, art, *, y=None):
...
ani = FuncAnimation(fig, partial(func, art=ln, y='foo'))
If ``blit == True``, *func* must return an iterable of all artists
that were modified or created. This information is used by the blitting
algorithm to determine which parts of the figure have to be updated.
Expand Down Expand Up @@ -1564,7 +1576,8 @@ def init_func() -> iterable_of_artists
value is unused if ``blit == False`` and may be omitted in that case.
fargs : tuple or None, optional
Additional arguments to pass to each call to *func*.
Additional arguments to pass to each call to *func*. Note: the use of
`functools.partial` is preferred over *fargs*. See *func* for details.
save_count : int, default: 100
Fallback for the number of values from *frames* to cache. This is
Expand Down

0 comments on commit 8e3f120

Please sign in to comment.