迭代器

迭代器，迭代器最早出現在1974年設計的CLU程式語言中。在各種語言實作迭代器的方式皆不盡同，有些物件導向語言像Java、C#、Ruby、Python、Delphi都已將迭代器的特性內建語言當中，完美的跟語言整合，我們稱之隱式迭代器。但像是C++語言本身就沒有迭代器的特色，但STL仍利用模板實作了功能強大的迭代器。STL容器的資料的記憶體地址可能會重新分配，與容器繫結的迭代器仍然可以定位到重新分配後的正確的記憶體地址。描述.內部迭代器.內部的迭代器是高階函式，比如codice_1、 codice_2等，它實現跨經一個容器的遍歷，依次將給定函式應用到每個元素。外部迭代器和迭代器模式.外部的迭代器可以被認為是某種型別的指標，它有兩個主要操作：引用在一個物件。還必須有一種方式建立迭代器並指向容器的第一個元素，還要有某種方式確定何時迭代器已經窮盡了容器中所有的元素。依據語言和意向用途，迭代器還可以提供額外的操作或展示不同的行為。迭代器的主要用途是允許使用者處理一個容器的所有元素，而將使用者隔離於容器的內部結構。這允許容器以任何它希望的方式儲存元素，而允許使用者把它們看作就是簡單的序列或列表。迭代器類通常設計為緊密協作於對應的容器類。容器類通常提供建立迭代器的方法。迴圈計數器有時也被稱為迴圈迭代器。但是迴圈計數器只提供遍歷功能而不提供訪問功能。生成器.實現迭代器的一種方式是使用受限形式的協程，也叫做生成器。不同於子例程，生成器協程可以向它的呼叫者多次產生返回值，而非只是返回一次。多數迭代器可自然的表達為生成器，但是因為生成器在被多次啟用之間儲存了自己的區域性狀態，它們特別適合於複雜的、有狀態的迭代器，比如樹遍歷器。在不同的作者和語言之間，術語“生成器”和“迭代器”的用法上有微妙的差異和區別。有些語言將二者視為同一介面，有些語言如JavaScript則將之獨立化。在Python中，生成器是一個迭代器構造器，即返回一個迭代器的函式。下面的Python生成器返回一個斐波那契數列的迭代器，使用到了Python的codice_3語句：def fibonacci(limit):a, b = 0, 1for _ in range(limit):yield aa, b = b, a+bfor number in fibonacci(100): # 這個生成器構造了一個迭代器print(number)隱式迭代器.一些面嚮物件語言比如C#、C++、Lua、Perl、Python、Ruby，提供了迭代一個容器物件的元素的內建方式，而不用介入一個顯式的迭代器物件。實際的迭代器物件可以在現實中存在，即便如此，它也不被暴露在這個語言的原始碼中。隱式迭代器經常透過codice_4語句來顯現出來，比如下面的Python例子：for value in iterable:print(value)在Python中，可迭代者是可以被轉換成迭代器的一個物件，接著在這個codice_5迴圈期間從頭至尾迭代它，這是隱含完成的。在Smalltalk家族語言和受其啟發的語言中，它們可以由蒐集物件自身建立。比如下面Ruby例子：iterable.each do |value|puts valueend這種迭代風格有時叫做“內部迭代”，因為它的程式碼完全執行在可迭代物件的上下文。支援列表推導式或類似構造的語言，還可以在結果列表的構造期間使用隱式迭代器，比如在Python中：names = [person.name for person in roster if person.male]有時隱式迭代只能做到部份的隱藏實質。C++語言有一些用於隱式迭代的函式模板，比如codice_6。這些函式仍要求顯式的迭代器物件作為它們的初始輸入，但是後續的迭代不將迭代器物件暴露給使用者。串流.迭代器是對輸入串流的一種有用的抽象，串流提供了潛在的無限可迭代的的物件。一些語言，比如Perl和Python，將串流實現為迭代器。串流的可替代的實現包括資料驅動語言，比如AWK和sed。迭代器分類.迭代器範疇.迭代器可以依據功能而歸類，下面是迭代器範疇的一個列表:迭代器型別.不同的語言或它們所具有的函式庫定義了自己的迭代器的型別，下面是一個列表：語言範例.C♯.在C♯中，一種新形式的迭代器提供了函式語言程式設計中的生成器，使用codice_7類似於Python中使用的codice_3// Method that takes an iterable input (possibly an array)// and returns all even numbers.public static IEnumerable numbers)foreach(int i in numbers)if (i % 2 == 0) yield return i;C++.C++的STL可支援迭代器。templatevoid printall(InputIterator first, InputIterator last)for(; first != last; ++first)std::cout « *first « std::endl;Java.Java JDK 1.2 版開始支援迭代器。每一個迭代器提供codice_9以及codice_10方法，同時也支援remove()。Iterator iter = list.iterator();//Iterator iter = list.iterator(); in J2SE 5.0while (iter.hasNext())System.out.println(iter.next());Python.在Python中，迭代器是語言的基礎部份，而在很多情況下是不可見的，因為它們隱含的用在了codice_5上的隱式迭代：for value in sequence:print(value)Python字典的時候，可以直接在其上進行迭代：for key in dictionary:value = dictionary[key]print(key, value)或者在字典codice_12方法產生元組形式的對應鍵-值對的時候，在其上進行迭代：for key, value in dictionary.items():print(key, value)但是迭代器也可以被顯式的使用和定義。對於一個可迭代的序列型別或類，內建的函式codice_13可用來建立一個迭代物件。接著可以透過codice_9函式對這個迭代物件進行迭代；這個函式在內部使用codice_15方法，它返回這個容器中的下一個元素。當沒有元素剩餘的時候，引發codice_17異常。下面的例子展示與前例等價的使用顯式迭代器的在序列上的迭代：it = iter(sequence)while True:try:#value = it.next() # in Python 2.xvalue = next(it) # in Python 3.xexcept StopIteration:breakprint(value)任何使用者定義的類都可以透過定義返回迭代器物件的codice_18方法，支援標準迭代。接著迭代器物件需要定義返回下一個元素的codice_15方法。Python生成器實現了這個迭代協議。Ruby.Ruby程式設計師可以用yield關鍵字定義迭代器，又將迭代器和生成器分開。0..42.each do |n|puts nend...以及...for n in 0..42puts nendRust.使用Rust可以對向量的元素進行迭代，或者建立自己的迭代器。每個迭代器都有介面卡(map，filter，skip，take……)。for n in 0..42 {println!("{}", n);fibonacci()下面是一個自定義迭代器。for i in fibonacci().skip(4).take(4) {println!("{}", i);