没有全局变量的python动画

时间:2013-07-07 11:44:29

标签: python animation graphics matplotlib scipy

我正在撰写康威的生命游戏实施。我的第一次尝试只是在每次更新后使用matplotlib的imshow在1和0的NxN板上绘制板。但是,这不起作用,因为程序在显示情节时会暂停。你必须关闭图以获得下一个循环迭代。

我发现在matplotlib中有一个动画包,但它没有(或给出)变量,所以我见过的每个实现(偶数matplotlib's documentation)依赖于全局变量。

所以这里有两个问题:

1)这是一个可以使用全局变量的地方吗?我一直都认为这是永远一个好主意,但这只是教条吗?

2)你如何在没有全局变量的python中做这样的动画(即使它意味着放弃matplotlib,我猜;标准库总是首选)。

2 个答案:

答案 0 :(得分:4)

这些只是示例程序。您可以使用object而不是全局变量,如下所示:

class GameOfLife(object):
    def __init__(self, initial):
        self.state = initial
    def step(self):
        # TODO: Game of Life implementation goes here
        # Either assign a new value to self.state, or modify it
    def plot_step(self):
        self.step()
        # TODO: Plot here

# TODO: Initialize matplotlib here
initial = [(0,0), (0,1), (0,2)]
game = GameOfLife(initial)
ani = animation.FuncAnimation(fig, game.plot_step)
plt.show()

如果你真的想避免上课,你也可以像这样重写程序:

def step(state):
    newstate = state[:] # TODO Game of Life implementation goes here
    return newstate
def plot(state):
    # TODO: Plot here
def play_game(state):
    while True:
         yield state
         state = step(state)

initial = [(0,0), (0,1), (0,2)]
game = play_game(initial)
ani = animation.FuncAnimation(fig, lambda: next(game))
plt.show()

请注意,对于非数学动画(没有标签,图表,比例等),您可能更喜欢pygletpygame

答案 1 :(得分:1)

以下是使用没有自定义类的FuncAnimation的示例:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

def animate(data, im):
    im.set_data(data)

def step():
    while True:
        # replace this with Conway's Game of Life logic
        data = np.random.randn(10, 10)
        yield data

fig, ax = plt.subplots()
im = ax.imshow(np.random.randn(10, 10), interpolation='nearest')
ani = animation.FuncAnimation(
    fig, animate, step, interval=10, repeat=True, fargs=(im, ))
plt.show()

当你在函数中使用yield(而不是return)时,它会使函数成为generator生成器功能保存状态。每次在生成器返回的迭代器上调用next时,执行流程都会从中断的位置(从上一个yield表达式)开始。这就是为什么生成器是一种避免全局变量的方法 - 可能的全局变量只是生成器函数中的局部变量,并且它们的状态在调用next之间保存。


顺便说一下,警告“从不使用全局”并不够精确。我们一直使用全局变量。每次在模块级别导入模块时,模块对象都是全局的。每次在模块级别定义函数或类时,它都是全局的。使用全局变量没有任何问题(尽管从函数内部访问全局变量比访问函数的本地变速器更慢。但是,要注意预优化)。

或许这个告诫应该是“尝试永远不要使用改变状态的全局变量”。改变全局值的原因是因为改变全局的每个函数都变得无关紧要。该功能不再能够作为独立的代码单元来理解和测试。程序员用来解决问题的主要工具是将大问题分解成更小的问题。函数和类有助于将问题分解成更小的部分。但是当你使用变异全局变量时,你会失去这个好处。现在,头脑必须立即整理整个模块以理解代码。