5

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

我发现 matplotlib 中有一个动画包,但它不接受(或给出)变量,所以我见过的每个实现(甚至matplotlib 的文档)都依赖于全局变量。

所以这里有两个问题:

1)这是一个可以使用全局变量的地方吗?我一直读到这从来都不是一个好主意,但这只是教条吗?

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

4

2 回答 2

5

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

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

于 2013-07-07T11:58:48.557 回答
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.


顺便说一句,“永远不要使用全局变量”的警告不够精确。我们一直使用全局变量。每次在模块级别导入模块时,模块对象都是全局的。每次在模块级别定义函数或类时,它都是全局的。使用全局变量并没有错(尽管从函数内部访问全局变量确实比访问函数的局部变量要慢。不过,请注意预优化)。

也许建议改为“尽量不要使用改变状态的全局变量”。改变全局值不好的原因是因为改变全局的每个函数都变得默默相关。该功能不再可以作为一个孤立的代码单元来理解和测试。程序员用来解决问题的主要工具是将大问题分解成更小的部分。函数和类有助于将问题分解成更小的部分。但是当你使用变异全局变量时,你会失去这个好处。大脑现在必须立即了解整个模块才能理解代码。

于 2013-07-07T13:36:49.437 回答