Last active
June 7, 2016 16:59
-
-
Save sodastsai/ae6be68196402f2b8e82ccd1caa72aeb to your computer and use it in GitHub Desktop.
Iterable, Iterator, and Generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
For Python and ES6: | |
Iterables: | |
- 有辦法被套在 `for ... in ...` (Python) or `for ... of ...` (ES6) | |
- 可以一直重複被列舉內容 | |
- For Python: 有個 method 叫 `__iter__` 會回傳 iterator | |
- For ES6: 有個 attribute 叫 `Symbol.iterator` 會回傳 iterator | |
Iterators: | |
- 可以有效率(效能跟記憶體使用上)的列舉出 collection 中的內容 | |
- 有點像一般 db (例如 sqlite)的 cursor 的感覺 | |
- 一次性的, 走完(列舉完)就g了不能用了 | |
- For Python 2 and ES6: 有一個 method 叫 `next` 會回傳 collection 中還沒看過的東西(下一個要被吐出來的東西) | |
- For Python 3: 有一個 method 叫 `__next__` 會回傳 collection 中還沒看過的東西(下一個要被吐出來的東西) | |
- For Python 3.6-: 直接回傳 value, 沒東西就 raise StopIteration (before Python 3.6) | |
- For Python 3.6+: Python 3.6 (PEP 479) 起, 沒東西改成 `return None` | |
- For Python: Iterators 同時也是 Iterables | |
- For ES6: 有就回傳 `{value, done: false}`, 沒東西就 `return {value: undefined, done: true}`` | |
Generators: | |
- 用 `yield` 「連續」回傳一個東西, 快速做出一個 Iterator | |
- Generators 同時也是 Iterators | |
- Python 的文件說: | |
Generators are a simple and powerful tool for creating iterators. | |
They are written like regular functions but use the yield statement | |
whenever they want to return data. Each time next() is called on it, | |
the generator resumes where it left off | |
(it remembers all the data values and which statement was last executed). | |
- For Python: 任何 function 只要有用 `yield` 吐東西就是 | |
- For Python: 有 generator expression --> `(x*x for x in [1, 2, 3])` --> 把數字平方的 generator | |
- For ES6: 用 `function *` 表示 generator, 用 `yield` 吐東西 | |
Swift: | |
- Swift 也有 Generator | |
```swift | |
protocol Generator { | |
associatedtype Element | |
func next() -> Element? | |
} | |
``` | |
- 其實他訂的比較像 Python/ES6 的 Iterator | |
- `typealias Element` 這邊是當作 Generic Type 的用法 | |
- `next` 有東西就回傳, 沒東西就 `return nil` | |
- 實作 `SequenceType` 這個 Protocol 來達到 Iterables 的效果(包含可以 `for ... in ...`) | |
http://nvie.com/posts/iterators-vs-generators/ | |
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators | |
http://jsrocks.org/2015/09/javascript-iterables-and-iterators/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Iterator(n) { | |
let i = 0; | |
return { | |
next: function() { | |
return i < n ? {value: i++, done: false} : {done: true}; | |
} | |
}; | |
} | |
function Iterable(n) { | |
const i = {}; | |
i[Symbol.iterator] = function() { return Iterator(n) }; | |
return i; | |
} | |
function* Generator(n) { | |
let i = 0; | |
while (i < n) { | |
yield i++; | |
} | |
} | |
function iteratorToArray(itor) { | |
let done = false; | |
const result = []; | |
while (!done) { | |
const next = itor.next(); | |
done = next.done; | |
if (!done) { | |
result.push(next.value); | |
} | |
} | |
return result; | |
} | |
const iterator = Iterator(5); | |
console.log(iteratorToArray(iterator)); // [0, 1, 2, 3, 4] | |
console.log(iteratorToArray(iterator)); // [], iterator is not reusable | |
const iterable = Iterable(5); | |
console.log([...iterable]); // [0, 1, 2, 3, 4] | |
console.log([...iterable]); // [0, 1, 2, 3, 4], iterable is reusable | |
const generator = Generator(5); | |
console.log(iteratorToArray(generator)); // [0, 1, 2, 3, 4] | |
console.log(iteratorToArray(generator)); // [], generator is not reusable |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Iterator(object): | |
def __init__(self, n): | |
self.i = 0 | |
self.n = n | |
def __iter__(self): | |
return self | |
# Python 3+, 3.6- | |
def __next__(self): | |
if self.i < self.n: | |
value = self.i | |
self.i += 1 | |
return value | |
else: | |
raise StopIteration() | |
# Python 2 | |
def next(self): | |
return self.__next__() | |
class Iterable(object): | |
def __init__(self, n): | |
self.n = n | |
def __iter__(self): | |
return Iterator(self.n) | |
def Generator(n): | |
i = 0 | |
while i < n: | |
yield i | |
i += 1 | |
iterator = Iterator(5) | |
print(list(iterator)) # [0, 1, 2, 3, 4] | |
print(list(iterator)) # [], iterator runs only once | |
iterable = Iterable(5) | |
print(list(iterable)) # [0, 1, 2, 3, 4] | |
print(list(iterable)) # [0, 1, 2, 3, 4], iteratable is re-runnable | |
generator = Generator(5) | |
print(list(generator)) # [0, 1, 2, 3, 4] | |
print(list(generator)) # [], generators return iterators |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func Generator(n: Int) -> AnyGenerator<Int> { | |
var i = 0 | |
return AnyGenerator { | |
while i < n { | |
let value = i | |
i += 1 | |
return value | |
} | |
return nil | |
} | |
} | |
func generatorToArray<T, G: GeneratorType where G.Element == T>(generator: G) -> [T] { | |
var _generator = generator | |
var result = [T]() | |
while let i = _generator.next() { | |
result.append(i) | |
} | |
return result | |
} | |
let generator = Generator(5) | |
print(generatorToArray(generator)) // [0, 1, 2, 3, 4] | |
print(generatorToArray(generator)) // [], Generator (Iterator in Py/ES6) is not reusable |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment