生成器 (计算机编程)

生成器是電腦科學中特殊的子程式。實際上，所有生成器都是疊代器。生成器非常類似於返回陣列的函式，都是具有參數、可被呼叫、產生一系列的值。但是生成器不是構造出陣列包含所有的值並一次性返回，而是每次產生一個值，因此生成器看起來像函式，但行為像疊代器。 
生成器可以用更有表達力的控制流結構實現，如協程或頭等計算續體。 生成器，也被稱作半協程（semicoroutine），是特殊的、能力更弱的協程，總是在傳回一個值時把控制交還給呼叫者，而不是像協程那樣指出另一個協程繼續執行。

使用

生成器通常在一個迴圈內部被呼叫。  生成器第一次被呼叫是在進入這個迴圈結構時，建立一個物件以封裝生成器的狀態、繫結的實參。生成器的實體接著被執行直至遇到一個特別的yield動作，在這裡提供給yield動作的值被返回給呼叫者。在下一次呼叫同一個生成器的時候，生成器從yield動作之後恢復執行，直到遇上另一個yield動作。生成器的執行也可以遇到finish動作而終止。 
由於生成器計算它的要被yield的值是按需的，因此可以用來代表一個流，一次性全部計算出來是昂貴的甚至是不可能的，或是無窮序列或直播資料序列。 
如果需要迅速求值，可以使用列表或使用並列結構來建立一個列表。例如，Python的一個生成器g可被求值到列表l通過l = list(g)。  
生成器可用於在運算式中完成傳統的迴圈結構的功能。

歷史

生成器最早出現於CLU語言 (1975)。 
現在，Python, C#, Ruby, 最新版本的ECMAScript (ES6/ES2015)與其他語言。在CLU與C#，生成器稱作iterators, 在Ruby稱作enumerators.

C++

使用宏預處理的例子見:
$generator(descent){
   // place for all variables used in the generator
   int i; // our counter

   // place the constructor of our generator, e.g. 
   // descent(int minv, int maxv) {...}
   
   // from $emit to $stop is a body of our generator:
    
   $emit(int) // will emit int values. Start of body of the generator.
      for (i = 10; i > 0; --i)
         $yield(i); // a.k.a. yield in Python,
                    // returns next number in [1..10], reversed.
   $stop; // stop, end of sequence. End of body of the generator.};
可疊代：
int main(int argc, char* argv[]){
  descent gen;
  for(int n; gen(n);) // "get next" generator invocation
    printf("next number is %d\n", n);
  return 0;}
C++11提供的foreach loop可用於任何具有begin與end成員函式的類。還需要有operator!=, operator++ 與operator*。例如：
#include <iostream>int main(){
    for (int i: range(10))
    {
        std::cout << i << std::endl;
    }
    return 0;}
一個基本實現：
class range{private:
    int last;
    int iter;public:
    range(int end):
        last(end),
        iter(0)
    {}

    // Iterable functions
    const range& begin() const { return *this; }
    const range& end() const { return *this; }

    // Iterator functions
    bool operator!=(const range&) const { return iter < last; }
    void operator++() { ++iter; }
    int operator*() const { return iter; }};

C#

C# 2.0開始可以利用yield構造生成器。
// Method that takes an iterable input (possibly an array)// and returns all even numbers.public static IEnumerable<int> GetEven(IEnumerable<int> numbers) {
    foreach (int i in numbers) {
        if ((i % 2) == 0) {
            yield return i;
        }
    }}
可以使用多個yield return語句： 
public class CityCollection : IEnumerable<string> {
    public IEnumerator<string> GetEnumerator() {
        yield return "New York";
        yield return "Paris";
        yield return "London";
    }}

Python

2.2版開始支援生成器。
def countfrom(n):
    while True:
        yield n
        n += 1# Example use: printing out the integers from 10 to 20.# Note that this iteration terminates normally, despite # countfrom() being written as an infinite loop.for i in countfrom(10):
    if i <= 20:
        print(i)
    else:
        break# Another generator, which produces prime numbers indefinitely as needed.def primes():
    yield 2
    n = 3
    p = []
    while True:
        # This works in Python 2.5+ 
        if not any(n % f == 0 for f in 
                     itertools.takewhile(lambda f: f*f <= n, p)): 
            yield n
            p.append(n)
        n += 2
Python的生成器可以認為是一個疊代器包含了凍結的堆疊框。當用next()方法呼叫疊代器，Python恢復凍結的堆疊框，繼續執行至下一次的yield語句。生成器的堆疊框再一次凍結，被yield的值返回給呼叫者。 
PEP 380 (Python 3.3開始)增加了yield from運算式，允許生成器委託它的行為給另一個生成器。

生成器運算式

Python的一種語法類比了列表推導。
squares = ( n*n  for n in countfrom(2) )for j in squares:
    if j <= 20:
        print(j)
    else:
        break