๋ฐ๋ณต์์ ์์ฑ๊ธฐ์ ์ฐจ์ด์ ์ ๋ฌด์์ ๋๊น? ๊ฐ ์ฌ๋ก๋ฅผ ์ธ์ ์ฌ์ฉํ ๊ฒ์ธ์ง์ ๋ํ ๋ช ๊ฐ์ง ์๊ฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
๋ต๋ณ
iterator
๋ณด๋ค ์ผ๋ฐ์ ์ธ ๊ฐ๋
์
๋๋ค. ํด๋์ค์ next
๋ฉ์๋ ( __next__
Python 3)์ ๊ทธ __iter__
๋ฉ์๋ ๊ฐ์๋ ๊ฐ์ฒด์
๋๋ค return self
.
๋ชจ๋ ์์ฑ๊ธฐ๋ ๋ฐ๋ณต์์ด์ง๋ง ๊ทธ ๋ฐ๋๋ ์๋๋๋ค. ์ ๋๋ ์ดํฐ๋ ํ๋ ์ด์์ yield
ํํ์ ( yield
Python 2.5 ๋ฐ ์ด์ ๋ฒ์ ์ ๋ช
๋ น๋ฌธ) ์ด์๋ ํจ์๋ฅผ ํธ์ถํ์ฌ ๋น๋๋๋ฉฐ ์ด์ ๋จ๋ฝ์์ ์ ์๋ฅผ ์ถฉ์กฑ์ํค๋ ๊ฐ์ฒด์
๋๋ค iterator
.
์ํ ์ ์ง๊ฐ ๋ค์ ๋ณต์กํ ํด๋์ค๊ฐ ํ์ํ๊ฑฐ๋ next
(and __iter__
๋ฐ __init__
) ์ด์ธ์ ๋ค๋ฅธ ๋ฉ์๋๋ฅผ ๋
ธ์ถํ๋ ค๋ ๊ฒฝ์ฐ ์์ฑ๊ธฐ ๋์ ์ฌ์ฉ์ ์ ์ ๋ฐ๋ณต์๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ ์ ์์ต๋๋ค . ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ ๋๋ ์ดํฐ (๋๋ก๋ ์ถฉ๋ถํ ๊ฐ๋จํ ์๊ตฌ, ์ ๋๋ ์ดํฐ ํํ์ )๋ก ์ถฉ๋ถํ๋ฉฐ ์ํ ์ ์ง (ํฉ๋นํ ํ๊ณ ๋ด)๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ ์์ด ์ผ์ ์ค์ง๋๊ณ ์ฌ๊ฐ ๋จ์ผ๋ก์จ โ์๋ฃโ๋๊ธฐ ๋๋ฌธ์ ์ฝ๋ฉ์ด ๋ ๊ฐ๋จํฉ๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ ์์ฑ๊ธฐ :
def squares(start, stop):
for i in range(start, stop):
yield i * i
generator = squares(a, b)
๋๋ ๋ฑ๊ฐ ์์ฑ๊ธฐ ํํ์ (genexp)
generator = (i*i for i in range(a, b))
์ฌ์ฉ์ ์ ์ ๋ฐ๋ณต์๋ก ๋น๋ํ๋ ค๋ฉด ๋ ๋ง์ ์ฝ๋๊ฐ ํ์ํฉ๋๋ค.
class Squares(object):
def __init__(self, start, stop):
self.start = start
self.stop = stop
def __iter__(self): return self
def next(self): # __next__ in Python 3
if self.start >= self.stop:
raise StopIteration
current = self.start * self.start
self.start += 1
return current
iterator = Squares(a, b)
๊ทธ๋ฌ๋ ๋ฌผ๋ก ์์
์ ํตํด Squares
์ถ๊ฐ ๋ฐฉ๋ฒ์ ์ฝ๊ฒ ์ ๊ณต ํ ์ ์์ต๋๋ค.
def current(self):
return self.start
์์ฉ ํ๋ก๊ทธ๋จ์์ ์ด๋ฌํ ์ถ๊ฐ ๊ธฐ๋ฅ์ด ์ค์ ๋ก ํ์ํ ๊ฒฝ์ฐ.
๋ต๋ณ
๋ฐ๋ณต์์ ์์ฑ๊ธฐ์ ์ฐจ์ด์ ์ ๋ฌด์์ ๋๊น? ๊ฐ ์ฌ๋ก๋ฅผ ์ธ์ ์ฌ์ฉํ ๊ฒ์ธ์ง์ ๋ํ ๋ช ๊ฐ์ง ์๊ฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
์์ฝ : ๋ฐ๋ณต์๋์ด ๊ฐ์ฒด __iter__
์์ __next__
( next
ํ์ด์ฌ 2) ๋ฐฉ๋ฒ. ์์ฑ๊ธฐ๋ ๋ฐ๋ณต๊ธฐ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ์ฝ๊ณ ๋ด์ฅ ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค.
yield๊ฐ์๋ ํจ์๋ ์ฌ์ ํ ํธ์ถ๋๋ ๊ฒฝ์ฐ ์์ฑ๊ธฐ ๊ฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ ํจ์์ ๋๋ค.
def a_function():
"when called, returns generator object"
yield
์์ฑ๊ธฐ ํํ์์ ๋ํ ์์ฑ๊ธฐ๋ฅผ ๋ฐํํฉ๋๋ค.
a_generator = (i for i in range(0))
๋ณด๋ค ์ฌ์ธต์ ์ธ ์ค๋ช ๊ณผ ์์ ๋ฅผ ๋ณด๋ ค๋ฉด ๊ณ์ ์ฝ์ผ์ญ์์ค.
์์ฑ๊ธฐ ๋ ๋ฐ๋ณต์์ ๋๋ค
ํนํ generator๋ ์ดํฐ๋ ์ดํฐ์ ํ์ ์ ํ์ ๋๋ค.
>>> import collections, types
>>> issubclass(types.GeneratorType, collections.Iterator)
True
๋ช ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์์ฑ๊ธฐ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ๊ฐ์ฅ ์ผ๋ฐ์ ์ด๊ณ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
ํนํ ์์จ์ด์๋ ํจ์๋ ํธ์ถ๋๋ฉด ์์ฑ๊ธฐ๋ฅผ ๋ฐํํ๋ ํจ์์ ๋๋ค.
>>> def a_function():
"just a function definition with yield in it"
yield
>>> type(a_function)
<class 'function'>
>>> a_generator = a_function() # when called
>>> type(a_generator) # returns a generator
<class 'generator'>
๊ทธ๋ฆฌ๊ณ ์์ฑ๊ธฐ๋ ๋ค์ ๋ฐ๋ณต์์ ๋๋ค.
>>> isinstance(a_generator, collections.Iterator)
True
๋ฐ๋ณต์ ๋ ๋ฐ๋ณต ๊ฐ๋ฅ
Iterator๋ Iterable์ ๋๋ค.
>>> issubclass(collections.Iterator, collections.Iterable)
True
__iter__
๋ฐ๋ณต์๋ฅผ ๋ฐํ ํ๋ ๋ฉ์๋๊ฐ ํ์ํฉ๋๋ค .
>>> collections.Iterable()
Traceback (most recent call last):
File "<pyshell#79>", line 1, in <module>
collections.Iterable()
TypeError: Can't instantiate abstract class Iterable with abstract methods __iter__
iterables์ ๋ช ๊ฐ์ง ์๋ ๋ด์ฅ ํํ, ๋ชฉ๋ก, ์ฌ์ , ์ธํธ, โโ๊ณ ์ ๋ ์ธํธ, ๋ฌธ์์ด, ๋ฐ์ดํธ ๋ฌธ์์ด, ๋ฐ์ดํธ ๋ฐฐ์ด, ๋ฒ์ ๋ฐ ๋ฉ๋ชจ๋ฆฌ ๋ทฐ์ ๋๋ค.
>>> all(isinstance(element, collections.Iterable) for element in (
(), [], {}, set(), frozenset(), '', b'', bytearray(), range(0), memoryview(b'')))
True
๋ฐ๋ณต์ ์๋next
๋๋ __next__
๋ฉ์๋๊ฐ ํ์ ํฉ๋๋ค
ํ์ด์ฌ 2์์ :
>>> collections.Iterator()
Traceback (most recent call last):
File "<pyshell#80>", line 1, in <module>
collections.Iterator()
TypeError: Can't instantiate abstract class Iterator with abstract methods next
๊ทธ๋ฆฌ๊ณ ํ์ด์ฌ 3์์ :
>>> collections.Iterator()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Iterator with abstract methods __next__
๋ค์ iter
ํจ์ ๋ฅผ ์ฌ์ฉํ์ฌ ๋ด์ฅ ๊ฐ์ฒด (๋๋ ์ฌ์ฉ์ ์ ์ ๊ฐ์ฒด)์์ ๋ฐ๋ณต์๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค .
>>> all(isinstance(iter(element), collections.Iterator) for element in (
(), [], {}, set(), frozenset(), '', b'', bytearray(), range(0), memoryview(b'')))
True
__iter__
๋น์ ์ด์ ๋ํ ๋ฃจํ์ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ๋ฉด ๋ฉ์๋๊ฐ ํธ์ถ๋ฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ __next__
๋ฐ๋ณต์ ๊ฐ์ฒด ์์ ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋ฃจํ์ ๋ํ ๊ฐ ํญ๋ชฉ์ ๊ฐ์ ธ์ต๋๋ค. ๋ฐ๋ณต๊ธฐ๊ฐ StopIteration
์์ง๋๋ฉด ์ฌ๋ผ๊ฐ๊ณ ๊ทธ ์์ ์์ ์ฌ์ฌ์ฉ ํ ์ ์์ต๋๋ค.
์ค๋ช ์์์
๋ด์ฅ ์ ํ ๋ฌธ์ ์ ๋ฐ๋ณต์ ์ ํ ์น์ ์ ์์ฑ๊ธฐ ์ ํ ์น์ ์์ ๋ค์์ ์ํํ์ญ์์ค .
ํ์ด์ฌ์ ์์ฑ๊ธฐ๋ ๋ฐ๋ณต๊ธฐ ํ๋กํ ์ฝ์ ๊ตฌํํ๋ ํธ๋ฆฌํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ปจํ ์ด๋ ๊ฐ์ฒด์
__iter__()
๋ฉ์๋๊ฐ ์์ฑ์๋ก ๊ตฌํ๋๋ฉด,__iter__()
๊ทธ๋ฆฌ๊ณnext()
[__next__()
in Python 3] ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ ๋ฐ๋ณต์ ๊ฐ์ฒด (๊ธฐ์ ์ ์ผ๋ก ์์ฑ๊ธฐ ๊ฐ์ฒด)๋ฅผ ์๋์ผ๋ก ๋ฐํํฉ๋๋ค . ์์ฑ๊ธฐ์ ๋ํ ์์ธํ ๋ด์ฉ์ ์์ฐ๋ ํํ ์ค๋ช ์๋ฅผ ์ฐธ์กฐํ์ญ์์ค.
(๊ณตํฌ๋ ์ถ๊ฐ๋จ)
์ด๊ฒ์ผ๋ก๋ถํฐ ์ฐ๋ฆฌ๋ Generators๊ฐ (ํธ๋ฆฌํ) Iterator ์ ํ์ด๋ผ๋ ๊ฒ์ ์๊ฒ๋ฉ๋๋ค.
๋ฐ๋ณต์ ๊ฐ์ฒด ์
์์ ์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ฑฐ๋ ํ์ฅํ์ฌ Iterator ํ๋กํ ์ฝ์ ๊ตฌํํ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
class Yes(collections.Iterator):
def __init__(self, stop):
self.x = 0
self.stop = stop
def __iter__(self):
return self
def next(self):
if self.x < self.stop:
self.x += 1
return 'yes'
else:
# Iterators must raise when done, else considered broken
raise StopIteration
__next__ = next # Python 3 compatibility
๊ทธ๋ฌ๋ ๊ฐ๋จํ Generator๋ฅผ ์ฌ์ฉํ์ฌ์ด ์์ ์ ์ํํ๋ ๊ฒ์ด ๋ ์ฝ์ต๋๋ค.
def yes(stop):
for _ in range(stop):
yield 'yes'
๋๋ ๋ ๊ฐ๋จํ ์์ฑ๊ธฐ ํํ์ (๋ชฉ๋ก ์ดํด์ ๋น์ทํ๊ฒ ์๋) :
yes_expr = ('yes' for _ in range(stop))
๊ทธ๊ฒ๋ค์ ๋ชจ๋ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ฌ์ฉ๋ ์ ์์ต๋๋ค :
>>> stop = 4
>>> for i, y1, y2, y3 in zip(range(stop), Yes(stop), yes(stop),
('yes' for _ in range(stop))):
... print('{0}: {1} == {2} == {3}'.format(i, y1, y2, y3))
...
0: yes == yes == yes
1: yes == yes == yes
2: yes == yes == yes
3: yes == yes == yes
๊ฒฐ๋ก
๋ฐ๋ณต ๊ฐ๋ฅํ ๊ฐ์ฒด๋ก Python ๊ฐ์ฒด๋ฅผ ํ์ฅํด์ผ ํ ๋ Iterator ํ๋กํ ์ฝ์ ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ yield
Generator Iterator๋ฅผ ๋ฐํํ๊ฑฐ๋ Generator Expressions๋ฅผ ๊ณ ๋ คํ๋ ํจ์๋ฅผ ์ ์ํ๋ ๋ฐ ๊ฐ์ฅ ์ ํฉํฉ๋๋ค .
๋ง์ง๋ง์ผ๋ก ์์ฑ๊ธฐ๋ ์ฝ ๋ฃจํด์ผ๋ก ํจ์ฌ ๋ ๋ง์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. โ์ ์โํค์๋์ ๊ธฐ๋ฅ์ ๋ฌด์์
๋๊น? โ์ ๋ํ ๋ต๋ณ์ ๋ํ ์ค๋ช
๊ณผ ํจ๊ป ์์ฑ๊ธฐ๋ฅผ ์ค๋ช
yield
ํฉ๋๋ค.
๋ต๋ณ
๋ฐ๋ณต์ :
๋ฐ๋ณต์๋ next()
๋ฐฉ๋ฒ์ ์ฌ์ฉ ํ์ฌ ๋ค์ ์์ ๊ฐ์ ์ป๋ ๊ฐ์ฒด์
๋๋ค .
๋ฐ์ ๊ธฐ :
์ ๋๋ ์ดํฐ๋ yield
๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ฌ ์ผ๋ จ์ ๊ฐ์ ์์ฑํ๊ฑฐ๋ ์์ฑํ๋ ํจ์์
๋๋ค .
์ ๋๋ ์ดํฐ ํจ์ (์ : ์๋ ์์ ์ ํจ์)์์ ๋ฐํ ๋ next()
์ ๋๋ ์ดํฐ ๊ฐ์ฒด (์ : f
์๋ ์์ ์ ๊ฒฝ์ฐ)์ ๋ํ ๋ชจ๋ ๋ฉ์๋ ํธ์ถ์ foo()
๋ค์ ๊ฐ์ ์์๋๋ก ์์ฑํฉ๋๋ค.
์์ฑ๊ธฐ ํจ์๊ฐ ํธ์ถ๋๋ฉด ํจ์ ์คํ์ ์์ํ์ง ์๊ณ ๋ ์์ฑ๊ธฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค. next()
๋ฉ์๋๊ฐ ์ฒ์์ผ๋ก ํธ์ถ ๋๋ฉด ํจ์๋ yield ๋ฌธ์ ๋๋ฌ ํ ๋๊น์ง ์คํ์ ์์ํ์ฌ yield ๊ฐ์ ๋ฆฌํดํฉ๋๋ค. ์์จ์ ๋ง์ง๋ง ์คํ์ ๊ธฐ์ตํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ ๋ฒ์งธ next()
ํธ์ถ์ ์ด์ ๊ฐ์์ ๊ณ์๋ฉ๋๋ค.
๋ค์ ์์ ๋ ์์ฑ๊ธฐ ๊ฐ์ฒด์์ yield์ next ๋ฉ์๋ ํธ์ถ ๊ฐ์ ์ํธ ์์ฉ์ ๋ณด์ฌ์ค๋๋ค.
>>> def foo():
... print "begin"
... for i in range(3):
... print "before yield", i
... yield i
... print "after yield", i
... print "end"
...
>>> f = foo()
>>> f.next()
begin
before yield 0 # Control is in for loop
0
>>> f.next()
after yield 0
before yield 1 # Continue for loop
1
>>> f.next()
after yield 1
before yield 2
2
>>> f.next()
after yield 2
end
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
๋ต๋ณ
๊ธฐ์กด ๋ต๋ณ์ด ๊ณต์ ๋ฌธํ์ ํผ๋์ ๊ตฌ์ฒด์ ์ผ๋ก ๋ค๋ฃจ์ง ์์ผ๋ฏ๋ก ๋ต๋ณ ์ถ๊ฐ
์์ฑ๊ธฐ ํจ์ ๋yield
๋์ ์์ ์ ๋ ์ผ๋ฐ ํจ์์
๋๋คreturn
. ์ ๋๋ ์ดํฐ ํจ์๊ฐ ํธ์ถ๋๋ฉด ์ ๋๋ ์ดํฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค. ์ ๋๋ ์ดํฐ ๊ฐ์ฒด ๋next()
๋ฉ์๋์
๋๋ค. ๋ฅผ ํธ์ถnext()
ํ๋ฉด ์์ฑ๊ธฐ ํจ์์์ ์์ฑ ๋ ๋ค์ ๊ฐ์ด ๋ฐํ๋ฉ๋๋ค.
์ฝ์ Python ์์ค ๋ฌธ์์ ๋ฐ๋ผ ํจ์ ๋๋ ๊ฐ์ฒด๋ฅผ โ์ ๋๋ ์ดํฐโ๋ผ๊ณ ํ ์ ์์ต๋๋ค. ํ์ด์ฌ ์ฉ์ด๋ ๊ทธ๋์, ๋ฐ์ ๊ธฐ ๊ธฐ๋ฅ์ ๋งํ๋ค ํ์ด์ฌ ์ํค๊ฐ ๋ฐ์ ๊ฐ์ฒด๋ฅผ ์๋ฏธํ๋ค. ํ์ด์ฌ ํํ ๋ฆฌ์ผ์ ํ์ ํ๊ฒ ์์ํ๋ ๊ด๋ฆฌ ๋ ์ธ ๋ฌธ์ฅ์ ๊ณต๊ฐ์์ ์ฉ๋๋ฅผ :
์ ๋๋ ์ดํฐ๋ ์ดํฐ๋ ์ดํฐ๋ฅผ ๋ง๋๋ ๊ฐ๋จํ๊ณ ๊ฐ๋ ฅํ ๋๊ตฌ์ ๋๋ค. ๊ทธ๊ฒ๋ค์ ์ผ๋ฐ ํจ์์ฒ๋ผ ์์ฑ๋์ง๋ง ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ ค๊ณ ํ ๋๋ง๋ค yield ๋ฌธ์ ์ฌ์ฉํฉ๋๋ค. next ()๊ฐ ํธ์ถ ๋ ๋๋ง๋ค ์์ฑ๊ธฐ๋ ์ค๋จ ๋ ์์น์์ ์ฌ๊ฐํฉ๋๋ค (๋ชจ๋ ๋ฐ์ดํฐ ๊ฐ๊ณผ ๋ง์ง๋ง์ผ๋ก ์คํ ๋ ๋ช ๋ น๋ฌธ์ ๊ธฐ์ตํฉ๋๋ค).
์ฒ์ ๋ ๋ฌธ์ฅ์ ์์ฑ๊ธฐ ๊ธฐ๋ฅ์ด์๋ ์์ฑ๊ธฐ๋ฅผ ์๋ณํ๊ณ ์ธ ๋ฒ์งธ ๋ฌธ์ฅ์ ์์ฑ๊ธฐ ๊ฐ์ฒด๋ก ์๋ณํฉ๋๋ค.
์ด ๋ชจ๋ ํผ๋์๋ ๋ถ๊ตฌํ๊ณ , ๋ช ํํ๊ณ ์ต์ข ๋จ์ด์ ๋ํ ํ์ด์ฌ ์ธ์ด ์ฐธ์กฐ ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค .
yield ํํ์์ ์์ฑ๊ธฐ ํจ์๋ฅผ ์ ์ ํ ๋๋ง ์ฌ์ฉ๋๋ฉฐ ํจ์ ์ ์ ๋ณธ๋ฌธ์์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. ํจ์ ์ ์์์ yield ํํ์์ ์ฌ์ฉํ๋ฉด ํด๋น ์ ์๊ฐ ์ผ๋ฐ ํจ์ ๋์ ์์ฑ๊ธฐ ํจ์๋ฅผ ์์ฑํ๊ธฐ์ ์ถฉ๋ถํฉ๋๋ค.
์์ฑ๊ธฐ ํจ์๊ฐ ํธ์ถ๋๋ฉด ์์ฑ๊ธฐ๋ผ๋ ๋ฐ๋ณต๊ธฐ๋ฅผ ๋ฐํํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ํด๋น ์์ฑ๊ธฐ๋ ์์ฑ๊ธฐ ๊ธฐ๋ฅ์ ์คํ์ ์ ์ดํฉ๋๋ค.
๋ฐ๋ผ์ ๊ณต์์ ์ด๊ณ ์ ํํ ์ฌ์ฉ๋ฒ์์ โ์ ๋๋ ์ดํฐโ๋น ํ์ ์๋ ์์ฑ๊ธฐ ๊ธฐ๋ฅ์ด ์๋ ์์ฑ๊ธฐ ๊ฐ์ฒด๋ฅผ ์๋ฏธํฉ๋๋ค.
์์ ์ฐธ์กฐ๋ Python 2์ ๋ํ ๊ฒ์ด์ง๋ง Python 3 ์ธ์ด ์ฐธ์กฐ ๋ ๊ฐ์ ๊ฒ์ ๋งํฉ๋๋ค. ๊ทธ๋ฌ๋ ํ์ด์ฌ 3 ์ฉ์ด ๋
generator โฆ ์ผ๋ฐ์ ์ผ๋ก ์์ฑ๊ธฐ ๊ธฐ๋ฅ์ ๋ํ๋ด์ง ๋ง ์ผ๋ถ ์ํฉ์์๋ ์์ฑ๊ธฐ ๋ฐ๋ณต๊ธฐ๋ฅผ ๋ํ๋ผ ์๋ ์์ต๋๋ค. ์๋ ๋ ์๋ฏธ๊ฐ ๋ช ํํ์ง ์์ ๊ฒฝ์ฐ ์ ์ฒด ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจํธ์ฑ์ ํผํ ์ ์์ต๋๋ค.
๋ต๋ณ
๋ชจ๋ ์ฌ๋๋ค์ ์์ ๋ฅผ ํตํด ์ ๋ง ํ๋ฅญํ๊ณ ์์ธํ ๋ต๋ณ์ ์ป์์ผ๋ฉฐ ์ ๋ง ๊ฐ์ฌํฉ๋๋ค. ๋๋ ์ฌ์ ํ ๊ฐ๋ ์ ์ผ๋ก ๋ช ํํ์ง ์์ ์ฌ๋๋ค์ ์ํด ์งง์ ๋ช ์ค์ ๋ต๋ณ์์ฃผ๊ณ ์ถ์์ต๋๋ค.
์์ ๋ง์ ๋ฐ๋ณต์๋ฅผ ๋ง๋ค๋ฉด ์ฝ๊ฐ ๋ณต์กํฉ๋๋ค. ํด๋์ค๋ฅผ ๋ง๋ค๊ณ ์ต์ํ iter์ ๋ค์ ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผํฉ๋๋ค. ๊ทธ๋ฌ๋์ด ๋ฒ๊ฑฐ ๋ก์์ ํผํ๊ณ ๋ฐ๋ณต๊ธฐ๋ฅผ ๋น ๋ฅด๊ฒ ๋ง๋ค๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒํด์ผํฉ๋๊น? ๋คํ์ค๋ฝ๊ฒ๋ ํ์ด์ฌ์ ๋ฐ๋ณต์๋ฅผ ์ ์ํ๋ ์ง๋ฆ๊ธธ์ ์ ๊ณตํฉ๋๋ค. ์ ์ด๋ ํ ๋ฒ์ ํธ์ถ๋ก ํจ์๋ฅผ ์ ์ํ๊ธฐ ๋งํ๋ฉด๋ฉ๋๋ค. ์ด์ ํด๋น ํจ์๋ฅผ ํธ์ถ ํ๋ฉด ๋ฐ๋ณต์์ฒ๋ผ ์๋ํ๋ โ ๋ญ๊ฐ โ๋ฅผ ๋ฐํ ํฉ๋๋ค (๋ค์ ๋ฉ์๋๋ฅผ ํธ์ถํ๊ณ for ๋ฃจํ์์ ์ฌ์ฉํ ์ ์์). ์ด ์ผ์ด ์์ฑ๊ธฐ๋ผ๋ ํ์ด์ฌ์์ ์ด๋ฆ์ด
๊ทธ๊ฒ์ด ์กฐ๊ธ ๋ช ํ ํด์ง๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
๋ต๋ณ
์ด์ ๋ต๋ณ์์ด ์ถ๊ฐ ์ฌํญ์ ๋์ณค์ต๋๋ค. ์ ๋๋ ์ดํฐ์๋ close
๋ฉ์๋๊ฐ ์์ง๋ง ์ผ๋ฐ์ ์ธ ๋ฐ๋ณต์๋ ๊ทธ๋ ์ง ์์ต๋๋ค. ์ด close
๋ฉ์๋ StopIteration
๋ ์์ฑ๊ธฐ์์ ์์ธ๋ฅผ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค .finally
ํด๋น ๋ฐ๋ณต๊ธฐ ์ ์์ ์ ๋ฆฌ๋ฅผ ์คํํ ๊ธฐํ๋ฅผ ์ป์ต๋๋ค. ์ด ์ถ์ํ๋ ๋จ์ํ ๋ฐ๋ณต์๋ณด๋ค ๋๊ท๋ชจ์์ ๊ฐ์ฅ ์ ์ฉํฉ๋๋ค. ํ์ผ์ ๋ซ์ ์ ์์ผ๋ฏ๋ก ์์ฑ๊ธฐ๋ฅผ ๋ซ์ ์ ์์ต๋๋ค. ํ์ผ์ ๋ซ์ ํ์๊ฐ ์์ต๋๋ค.
์ฆ, ์ฒซ ๋ฒ์งธ ์ง๋ฌธ์ ๋ํ ๋์ ๊ฐ์ธ์ ์ธ ๋๋ต์ : iteratable์๋ __iter__
๋ฉ์๋ ๋ง ์๊ณ , ์ ํ์ ์ธ ๋ฐ๋ณต์๋ __next__
๋ฉ์๋ ๋ง ์๊ณ , ์ ๋๋ ์ดํฐ์๋ __iter__
a __next__
์ a ๋ฐ ์ถ๊ฐ๊ฐ close
์์ต๋๋ค.
๋ ๋ฒ์งธ ์ง๋ฌธ์ ๋ํด ๋ด ๊ฐ์ธ ์๋ต์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค ๋ ํ๋ ฅ ์ดํ ๊ณต์ฉ ์ธํฐํ์ด์ค์, ๋๋ ๋ฐ์ ๊ธฐ๋ฅผ ๋ง์ด ์ ํธํ๋ ๊ฒฝํฅ์ด ๋ค์ close
์ ๋ฉ์๋์ ๋ ํฐ์ ์กฐํฉ ์ฑ์ yield from
. ๋ก์ปฌ์์๋ ๋ฐ๋ณต์๋ฅผ ์ฌ์ฉํ ์ ์์ง๋ง ํํํ๊ณ ๊ฐ๋จํ ๊ตฌ์กฐ (๋ฐ๋ณต๊ธฐ๊ฐ ์ฝ๊ฒ ๊ตฌ์ฑ๋์ง ์์)์ด๊ณ ์ํ์ค๊ฐ โโ๋ค์ ์งง์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ ๋งํ ์ด์ ๊ฐ์๋ ๊ฒฝ์ฐ์๋ง ํนํ ์ํ์ค๊ฐ โโ๋๋๊ธฐ ์ ์ ์ค์ง ๋ ์ ์์ต๋๋ค. ๋ฆฌํฐ๋ด์ ์ ์ธํ๊ณ ๋ฐ๋ณต์๋ฅผ ๋ฎ์ ์์ค์ ํ๋ฆฌ๋ฏธํฐ๋ธ๋ก ๋ณด๋ ๊ฒฝํฅ์ด ์์ต๋๋ค.
์ ์ด ํ๋ฆ ๋ฌธ์ ์ ๊ฒฝ์ฐ ์์ฑ๊ธฐ๋ ์ฝ์๋งํผ์ด๋ ์ค์ํ ๊ฐ๋ ์ ๋๋ค. ๋ ๋ค ์ถ์์ ์ด๋ฉฐ ๊ตฌ์ฑ ๊ฐ๋ฅํฉ๋๋ค.
๋ต๋ณ
๋ฐ์ ๊ธฐ ๊ธฐ๋ฅ, ๋ฐ์ ๊ธฐ ๊ฐ์ฒด, ๋ฐ์ ๊ธฐ :
๋ฐ์ ๊ธฐ ๊ธฐ๋ฅ์ ํ์ด์ฌ์์ ์ ๊ท ๊ธฐ๋ฅ์ฒ๋ผ์ด์ง๋ง ํ๋ ์ด์ ํฌํจ๋์ด yield
๋ฌธ์. ์์ฑ๊ธฐ ํจ์๋ Iterator ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฅํ ํ ์ฝ๊ฒ ๋ง๋ค ์์๋ ํ๋ฅญํ ๋๊ตฌ ์
๋๋ค. ๋ฐ๋ณต์ ์์ฑ ๊ธฐ๋ฅ์ ์ํด ์ค๋ธ์ ํธ returend๋ ๋ถ๋ฆฐ๋ค ์์ฑ๊ธฐ ๊ฐ์ฒด ๋๋ ๋ฐ์ ๊ธฐ .
์ด ์์ ์์๋ Generator ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ Generator ํจ์๋ฅผ ๋ง๋ค์์ต๋๋ค <generator object fib at 0x01342480>
. ๋ค๋ฅธ ๋ฐ๋ณต์์ ๋ง์ฐฌ๊ฐ์ง๋ก Generator ๊ฐ์ฒด๋ for
๋ฃจํ์์ ๋๋ ๋ด์ฅ ํจ์ next()
๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ๊ธฐ์์ ๋ค์ ๊ฐ์ ๋ฐํ ํ ์ ์์ต๋๋ค.
def fib(max):
a, b = 0, 1
for i in range(max):
yield a
a, b = b, a + b
print(fib(10)) #<generator object fib at 0x01342480>
for i in fib(10):
print(i) # 0 1 1 2 3 5 8 13 21 34
print(next(myfib)) #0
print(next(myfib)) #1
print(next(myfib)) #1
print(next(myfib)) #2
๋ฐ๋ผ์ ์์ฑ๊ธฐ ํจ์๋ Iterator ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ ๋๋ค.
๋ฐ๋ณต์ :
๋ชจ๋ ์์ฑ๊ธฐ ๊ฐ์ฒด ๋ ๋ฐ๋ณต์ ์ด์ง๋ง ๊ทธ ๋ฐ๋๋ ์๋๋๋ค. ํด๋์ค๊ฐ ๊ตฌํ __iter__
ํ๊ณ __next__
๋ฉ์๋ (๋ฐ๋ณต์ ํ๋กํ ์ฝ์ด๋ผ๊ณ ๋ ํจ) ์ธ ๊ฒฝ์ฐ ์ฌ์ฉ์ ์ ์ ๋ฐ๋ณต์ ์ค๋ธ์ ํธ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค .
๊ทธ๋ฌ๋, ๋ฐ์ ๊ธฐ ์์ฑํ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒ์ด ํจ์ฌ ์ฝ๋ค ๋ฐ๋ณต์๋ฅผ ๊ทธ๋ค์ ์์ฑ์ ๋จ์ํํ๊ธฐ ๋๋ฌธ์,ํ์ง๋ง ์ฌ์ฉ์ ์ ์๋ ๋ฐ๋ณต์๋ ๋น์ ์๊ฒ ๋ ๋ง์ ์์ ๋ฅผ ์ ๊ณตํ๊ณ ์๋์ ์์ ๊ฐ์ด ๋น์ ์ ๋ํ ๋น์ ์ ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๊ตฌํํ ์ ์์ต๋๋ค.
class Fib:
def __init__(self,max):
self.current=0
self.next=1
self.max=max
self.count=0
def __iter__(self):
return self
def __next__(self):
if self.count>self.max:
raise StopIteration
else:
self.current,self.next=self.next,(self.current+self.next)
self.count+=1
return self.next-self.current
def __str__(self):
return "Generator object"
itobj=Fib(4)
print(itobj) #Generator object
for i in Fib(4):
print(i) #0 1 1 2
print(next(itobj)) #0
print(next(itobj)) #1
print(next(itobj)) #1