使用生成器(generator)和yield可以做哪些有趣的、酷酷的、让人意想不到的事情?
不限编程语言,例如python、javascript 等。
回复内容:yield 在 javascript 中用的最多的可能就是结合 promise/thunk 等实现异步操作,比如大名鼎鼎的 tj/co · github,所以已经不是「让人意想不到」的东西了。
理解 generator 的特性后,实现一个玩具版的 co 还是很简单的:
function async(generator) { return new promise(function(resolve, reject) { var g = generator() function next(val) { var result = g.next(val) var value = result.value if (!result.done) { value.then(next).catch(reject) } else { resolve(value) } } next() })}
最典型的不就是async/await么?
不了解yield怎么实现async/await的,用c#代码试举一例:
ienumerable> someasyncmethod(){ //blabla yield return await( asyncmethod, context ); //blabla yield return await( asyncmethod, context ); //blabla}
可以做动画呀,效果如图:
# -*- coding: utf-8 -*-import numpy as npimport matplotlib.pyplot as pltimport matplotlib.animation as animationimport math, random# 需要安装的库:numpy和matplotlib,推荐直接anacondafig, axes1 = plt.subplots()# 设置坐标轴长度axes1.set_ylim(0, 1.4)axes1.set_xlim(0, 1*np.pi/0.01)# 设置初始x、y数值数组xdata = np.arange(0, 2*np.pi, 0.01)ydata = np.sin(xdata)# 获得线条line, = axes1.plot(xdata)# 毛刺倍率,从0开始增长,offset越大毛刺越大offset = 0.0#因为update的参数是调用函数data_gen,所以第一个默认参数不能是framenumdef update(data): global offset line.set_ydata(data) return line,# 每次生成10个随机数据# 每次变化整幅图的话,yield一个整图就行了def data_gen(): global offset while true: length = float(len(xdata)) for i in range(len(xdata)): ydata[i]=math.sin(xdata[i])+0.2 if i>length/18.0 and i(length*2.7/6.0): ydata[i]+=offset*(random.random()-0.5) offset += 0.05 #可以设置offset的最大值 if offset>=0.5: offset=0.0 yield ydata# 配置完毕,开始播放ani = animation.funcanimation(fig, update, data_gen, interval=800, repeat=true)plt.show()
模拟离散事件,还有更简洁优雅的方式么
overview — simpy 3.0.8 documentation这个问题就是给我准备的嘛
当有人声称在cpython里实现了一个沙盒的时候就可以用yield去逗他了,i was looking through the code and saw someone submitted this but didn't run it:...
酷到没工作...a curious course on coroutines and concurrency 可以写出一个并发的库
generator tricks for systems programmers 可以写个流处理框架参见david beazley大神几次pycon的pdf,看完我简直是惊呆了。http://www.dabeaz.com可以用来训练神经网络.
比如lasagne/lasagne · github 中的一段示例代码:
def train(iter_funcs, dataset, batch_size=batch_size): train the model with `dataset` with mini-batch training. each mini-batch has `batch_size` recordings. num_batches_train = dataset['num_examples_train'] // batch_size num_batches_valid = dataset['num_examples_valid'] // batch_size for epoch in itertools.count(1): batch_train_losses = [] for b in range(num_batches_train): batch_train_loss = iter_funcs['train'](b) batch_train_losses.append(batch_train_loss) avg_train_loss = np.mean(batch_train_losses) batch_valid_losses = [] batch_valid_accuracies = [] for b in range(num_batches_valid): batch_valid_loss, batch_valid_accuracy = iter_funcs['valid'](b) batch_valid_losses.append(batch_valid_loss) batch_valid_accuracies.append(batch_valid_accuracy) avg_valid_loss = np.mean(batch_valid_losses) avg_valid_accuracy = np.mean(batch_valid_accuracies) yield { 'number': epoch, 'train_loss': avg_train_loss, 'valid_loss': avg_valid_loss, 'valid_accuracy': avg_valid_accuracy, }
tornado就是使用generator实现的协程(coroutine)模型,再配合event loop实现高并发的使用迭代器遍历二叉树。