JavaScript与Python的Generator

首先,Generator是函数式编程里的一个特性,他的特点是每一次执行都返回一个Generator对象,以供下次调用。Generator每次执行都只能执行到yield处,而且它可以保存之前generate的变量。

这样一来,我们就可以构造一个无限循环的Generator,用于特殊求值,下面以JavaScript用Generator求任意数量的素数为例:

用generator求任意数量素数的js实现

#!/usr/bin/node

function *primeGenerator() {
  let self = {
    num: 2,                   // Generator from 2
    primes: [],               // An array containing all prime numbers
    isPrime: true
  };

  while(true) {
    self.primes.forEach((prime) => {
      self.num % prime === 0 ? self.isPrime = false : void 0;
    });
    self.isPrime ? ( yield(self.num), self.primes.push(self.num)) : void(0);
    // Change the iteration condition
    self.num++, self.isPrime = true;
  }
}

let g = primeGenerator();

// Get any number of prime numbers
// In this case, we get the top 10 prime numbers
for (let i = 0; i < 10; i++) {
  console.log(g.next());
}

在上面的例子里,我们用generator求取了10个素数。当然,我们可以求任意数量的素数。

在首次调用primeGenerator后,我们获得了一个generator对象g。g执行到第一次的yield暂停住了,于是我们可以循环执行g.next,循环迭代,递推式自动获取素数。

上述js代码输出:

{ value: 2, done: false }
{ value: 3, done: false }
{ value: 5, done: false }
{ value: 7, done: false }
{ value: 11, done: false }
{ value: 13, done: false }
{ value: 17, done: false }
{ value: 19, done: false }
{ value: 23, done: false }
{ value: 29, done: false }

那么用Python如何实现呢?请看下面代码

用generator求任意数量素数的python实现

#!/usr/bin/python3

def primeGenerator(total):
    num = 2;
    primes = [];

    i = 0;
    while i < total:
        if [prime for prime in primes if num % prime is 0] == []:
            yield num               # num is prime
            primes.append(num)
            i += 1
        num += 1;

for i in primeGenerator(10):
    print(i)

同样可以得出正确的结果:

上述py代码输出:

2
3
5
7
11
13
17
19
23
29

不难发现,python中的generator可以用于“for…in…”迭代,其实javascript中的generator也可以用于for迭代,只不过是“for…of…”迭代,比如说:

#!/usr/bin/node

function *foo() {
  const contents = {
    foo: 'he',
    bar: 'llo,',
    baz: ' wo',
    qux: 'rld'
  };

  yield(contents.foo);
  yield(contents.bar);
  yield(contents.baz);
  yield(contents.qux);
  return void 0;
}

for (let value of foo()) {
  console.log(value)
}

输出:

he
llo,
 wo
rld

在Generator里,一但return,将结束整个迭代。

函数式程式设计语言里,都有Generator,包括Ruby,Haskell等。一些函数式编程后来者,比如PhP也有Generator。随着程式语言的发展,大家互相学习,吸收各自的优点,很多非函数式语言也有了Generator,比如Java。

Generator在某些复杂可无限迭代里显得十分有用,比如本文求任意数量的素数。

参考:

https://en.wikipedia.org/wiki/Generator_(computer_programming)

作者: YanWen

Web 开发者

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google photo

You are commenting using your Google account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s