且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在for循环中将事件与matplotlib一起使用

更新时间:2023-09-14 14:30:46

下一个块是您想要的 for 循环的作用.

This next block is what does what you want with the for loop.

def ugly_math():
    print 'you will hit this once'
    for j in range(10):
        print 'loop ', j
        # insert math here
        yield  np.random.random(10) * j

您的 for 循环进入函数 ugly_math ,而您想要绘制的是 yield 之后的内容.请参阅收益"是什么?Python 中的关键字 do? .简而言之, yield 将带有循环的函数转换为生成器工厂.

Your for loop goes into the function ugly_math, and what you want plotted is what goes after yield. see What does the "yield" keyword do in Python? . In short, yield turns a function with a loop into a generator factory.

fun = ugly_math()

那么就是一个生成器.当您调用 fun.next()时,它将运行函数 ugly_math ,直到达到 yield .然后它将返回产生的值(在本例中为 np.random.random ).下次您调用 fun.next() 时,它会从循环中停止的地方继续运行,直到再次达到 yield.因此,它完全符合您的要求.

is then a generator. When you call fun.next() it will run the function ugly_math until it hits the yield. It will then return the value yielded (in this example, np.random.random). The next time you call fun.next() it will pick up where it left off in the loop and run until it hits yield again. Hence it does exactly what you want.

然后从Holger大量借钱:

Then borrowing heavily from Holger:

fun = ugly_math()
cid_dict = {}
# Define the event
def ontype(event):
    if event.key == '1':
        print 'It is working'
        try:
            vector = fun.next()
            plt.plot(vector)
            fig.canvas.draw()
        except StopIteration:
            plt.gcf().canvas.mpl_disconnect(cid_dict['cid'])
            del cid_dict['cid']

# Create figure an connect the event to it
fig=plt.figure(figsize=(16,8))
cid_dict['cid'] = plt.gcf().canvas.mpl_connect('key_press_event',ontype)

vector = np.random.random(10)  
plt.plot(vector)
plt.show()

这里有 cid_dict ,这样我们就可以在用尽生成器之后删除回调.

The cid_dict is there so that we can remove the call-back after we have exhausted the generator.

我们可以把这一切都包装成一个类

We can wrap this all up into a class as such

class push_to_advance(object):
    def __init__(self):
        self.fig = plt.figure()
        self.ax = self.fig.gca()
        self.bound_keys = []
        self.bound_cid = {}

    def add_step_through(self, gen, key):
        key = key[0] # make a single char
        if key in self.bound_keys:
            raise RuntimeError("key %s already bound"%key)
        first_data = gen.next()
        self.ax.plot(first_data)
        self.fig.canvas.draw()
        self.bound_keys.append(key)
        def ontype(event):
            if event.key == key:
                try:
                    self.ax.plot(gen.next())
                    self.fig.canvas.draw()
                except StopIteration:
                    self.fig.canvas.mpl_disconnect(self.bound_cid[key])
                    del self.bound_cid[key]
                    self.bound_keys.remove(key)

        self.bound_cid[key] = self.fig.canvas.mpl_connect('key_press_event', ontype)

这是这样使用的:

 pta = push_to_advance()
 gen = ugly_math()
 pta.add_step_through(gen,'a')

任何可迭代的方法都需要一些技巧:

Any iterable will work with a bit of finessing:

 test_array = np.arange(100).reshape(10,10)
 pta.add_step_through(test_array.__iter__(), 'b')

这让我很开心,我把它保存为 gist.

This amused me enough I saved it as a gist.