JS generator
JS 生成器(generator)的语法
由function* 定义,并且,除了return语句,还可以用yield返回多次。
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
JS generator 使用
不断地调用generator对象的next()
用for … of循环迭代generator对象
//斐波那契数列生成器实现: 一次返回一个数,不断返回多次.
function* fib(max) {
var
t,
a = 0,
b = 1,
n = 1;
while (n < max) {
yield a;
t = a + b;
a = b;
b = t;
n ++;
}
return a;
}
//直接调用知识产生generator对象,还没有去执行。
fib(5);
// fib {[[GeneratorStatus]]: "suspended", [[GeneratorReceiver]]: Window};
//方法一
var f = fib(5);
// 执行到done为true时,这个generator对象就已经全部执行完毕,不要再继续调用next()了。
f.next(); // {value: 0, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 2, done: false}
//方法二
for (var x of fib(5)) {
console.log(x); // 依次输出0, 1, 1, 2, 3
}
JS generator 的优点
- generator可以在执行过程中多次返回,它看上去就像一个可以记住执行状态的函数,而用对象的属性来保存状态,相当繁琐。
- 可以将异步回调代码变成“同步”代码
ajax('http://url-1', data1, function (err, result) {
if (err) {
return handle(err);
}
ajax('http://url-2', data2, function (err, result) {
if (err) {
return handle(err);
}
ajax('http://url-3', data3, function (err, result) {
if (err) {
return handle(err);
}
return success(result);
});
});
});
//在generator时代,用AJAX时可以这么写:
try {
r1 = yield ajax('http://url-1', data1);
r2 = yield ajax('http://url-2', data2);
r3 = yield ajax('http://url-3', data3);
success(r3);
}
catch (err) {
handle(err);
}
python
python 生成器(generator)的语法
//(1)把一个列表生成式的[]改成()
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>
//(2)通过yield关键字定义的函数也是generator
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
python 生成器的使用
- generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
- 注意:用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中
//可以像js一样,调用next(g) 进行计算
//也可以像js一样,通过for循环来迭代对象
for n in g:
... print(n)
>>> g = fib(3)
>>> while True:
... try:
... x = next(g)
... print('g:', x)
... except StopIteration as e:
... print('Generator return value:', e.value)
... break
...
g: 1
g: 1
g: 2
Generator return value: done
//定义生成器计算杨辉三角
def triangles():
L = [1]
while True:
yield L
L.append(0)
L = [L[i - 1] + L[i] for i in range(len(L))]
//测试程序
n = 0
for t in triangles():
print(t)
n += 1
if n == 10:
break