μ½λ - ν¨μΊ μμ μ½λ μ°Έκ³ (ν¨μΊ μμ μ 리)
<μ΄μ κΈ>
https://silvercoding.tistory.com/29
[python μ¬ν] 12. λ΄λΆ iter ν¨μ, μ λλ μ΄ν°(Generator)
μ½λ - ν¨μΊ μμ μ½λ μ°Έκ³ (ν¨μΊ μμ μ 리) <μ΄μ κΈ> https://silvercoding.tistory.com/28 https://silvercoding.tistory.com/27 https://silvercoding.tistory.com/26 https://silvercoding.tistory.com/25..
silvercoding.tistory.com
* yield : λ©μΈ λ£¨ν΄ (μμ°¨μ§ν - νλμ νλ¦) <-> μλΈλ£¨ν΄ (ν¨μκ° νΈμΆλλ©΄ ν¨μκ° μλ κ³³μΌλ‘) μ΄ λ£¨ν΄ λκ°λ₯Ό λμμ ν μ μκ² ν΄μ£Όλ κ² yieldμ΄λ€.
* μ½λ£¨ν΄ μ μ΄ , μ½λ£¨ν΄ μν, μλ°©ν₯ κ° μ μ‘ (μλ°©ν₯ ν΅μ )
* μλΈ λ£¨ν΄ : λ©μΈλ£¨ν΄μμ 리ν΄μ μν΄ νΈμΆ λΆλΆμΌλ‘ λμμ λ€μ νλ‘μΈμ€
* μ½λ£¨ν΄ : λ£¨ν΄ μ€ν μ€ λ©μΆ€ κ°λ₯ -> νΉμ μμΉλ‘ λμκ°λ€κ° -> λ€μ μλ μμΉλ‘ λμμ μν κ°λ₯ -> λμμ± νλ‘κ·Έλλ° κ°λ₯νκ² ν΄μ€
*μ°λ λ : μ±κΈμ°λ λ -> λ©ν°μ°λ λ -> 볡μ‘νλ€! (곡μ λλ μμμ λν κ΅μ°©μν λ°μ κ°λ₯μ±μ΄ μμΌλ―λ‘ μ£ΌμκΉκ² μ½λ©ν΄μΌ ν¨) / 컨ν μ€νΈ μ€μμΉ λΉμ© λ°μ, μμ μλΉ κ°λ₯μ± μ¦κ°
- μ½λ£¨ν΄ μμ 1
def coroutine1():
print('>>> coroutine started.')
i = yield
print('>>> coroutine received : {}'.format(i))
μ λ² κΈμμλ yield i <-- μ΄λ° μμΌλ‘ μ¬μ©νλλ° , μ΄λ²μλ i = yield μ ννλ‘ μ¬μ©νμ¬ λ©μΈ 루ν΄μμ κ°μ μ λ¬ λ°μ μ μλ€.
* μ λλ μ΄ν° μ μΈ
c1 = coroutine1()
print('EX1-1 - ', c1, type(c1))
EX1-1 - <generator object coroutine1 at 0x000001430D3574F8> <class 'generator'>
μ λλ μ΄ν° κ°μ²΄λ₯Ό μμ±νμλ€.
next(c1)
next(c1)
>>> coroutine started.
>>> coroutine received : None
Traceback (most recent call last):
File "c:/Users/./Desktop/python_high/chapter06_02.py", line 35, in <module>
next(c1)
StopIteration
μμκ°μ΄ κ°μ μ μ‘νμ§ μμΌλ©΄ κΈ°λ³Έμ μΌλ‘ Noneμ μ μ‘νλ€.
* κ° μ μ‘
next(c1)
c1.send(100)
>>> coroutine started.
>>> coroutine received : 100
Traceback (most recent call last):
File "c:/Users/./Desktop/python_high/chapter06_02.py", line 41, in <module>
c1.send(100)
StopIteration
μ΄λ κ² next() λμ send()λ‘ κ°μ μ λ¬ν μ μλ€.
* μλͺ»λ μ¬μ©
c2 = coroutine1()
c2.send(100) # μμΈ λ°μ
Traceback (most recent call last):
File "c:/Users/./Desktop/python_high/chapter06_02.py", line 45, in <module>
c2.send(100) # μμΈ λ°μ
TypeError: can't send non-None value to a just-started generator
next()λ₯Ό νΈμΆνμ§ μκ³ , μ²μλΆν° sendλ₯Ό μ¬μ©νλ©΄ μμΈκ° λ°μνκ² λλ€! ( λ€μμ nextλ₯Ό νΈμΆνμ§ μμλ λλ λ°©λ²μ λ°°μΈ κ²μ΄λ€. )
- μ½λ£¨ν΄ μμ 2
* GEN_CREATED : μ²μ λκΈ° μν
* GEN_RUNNING : μ€ν μν
* GEN_SUSPENDED : yield λκΈ° μν
* GEN_CLOSED : μ€ν μλ£ μν
def coroutine2(x):
print('>>> coroutine started : {}'.format(x))
y = yield x
print('>>> coroutine received : {}'.format(y))
z = yield x + y
print('>>> coroutine received : {}'.format(z))
c3 = coroutine2(10)
coroutine2 ν¨μλ₯Ό μμ±νκ³ κ°μ²΄λ₯Ό ν λΉν΄ μ€λ€. xλ 10μΌλ‘ λ£μ΄μ€λ€.
from inspect import getgeneratorstate
from typing_extensions import Literal
print('EX1-2 - ', getgeneratorstate(c3))
print(next(c3))
print('EX1-3 - ', getgeneratorstate(c3))
print(c3.send(15))
print(c3.send(20)) # μμΈ
EX1-2 - GEN_CREATED
getgeneratorstateλ₯Ό μ΄μ©νμ¬ μ λλ μ΄ν°μ μνλ₯Ό κ°μ Έμμ νμΈν μ μλ€. μ°μ κ°μ²΄λ§ μμ±νμ λ μ²μ λκΈ° μνμμ νμΈν μ μλ€.
>>> coroutine started : 10
10
xκ°μ΄ λ°νλκ³ , μ΄ μνμμ λκΈ°νλ€.
EX1-3 - GEN_SUSPENDED
yield λκΈ° μν μμ νμΈν μ μλ€.
>>> coroutine received : 15
25
κ·Έλ€μ sendλ‘ 15λ₯Ό 보λ΄λ©΄ λ©μΆ°μλ yield μνμμ yμ κ° 15κ° μ λ¬λλ€. printλ¬ΈμΌλ‘ 15κ° μ μ λ¬λ κ²μ λ³Ό μ μκ³ , κ·Έ λ€μ yieldμ x + y κ° λ°νλκ³ μ΄μνμμ λ©μΆλ€.
>>> coroutine received : 20
λ λ€μ sendλ‘ 20μ 보λ΄λ©΄ yield λκΈ° μνμμ λ©μΆμ΄ μλ zμ κ°μ΄ μ λ¬λ κ²μ λ³Ό μ μλ€.
Traceback (most recent call last):
File "c:/Users/./Desktop/python_high/chapter06_02.py", line 78, in <module>
print(c3.send(20)) # μμΈ
StopIteration
κ·Έλ€μ yieldκ° μμΌλ―λ‘ μ€λ₯κ° λκ² λλ€.
- λ°μ½λ μ΄ν° ν¨ν΄
: nextλ₯Ό νΈμΆνμ§ μμλ λλ€!
<λ°μ½λ μ΄ν° ν¬μ€ν >
https://silvercoding.tistory.com/26
[python μ¬ν] 9. λ³μ λ²μ, Closure, Decorator
μ½λ - ν¨μΊ μμ μ½λ μ°Έκ³ (ν¨μΊ μμ μ 리) <μ΄μ κΈ> https://silvercoding.tistory.com/25 μ΄λ² ν¬μ€νΈμμλ λ°μ½λ μ΄ν°λ₯Ό μμλ³Ό κ²μ΄λ€. λ°μ½λ μ΄ν°λ μ΄λ ΅λ€κ³ λλΌλ κ²μ΄ λΉμ°νλ€. λ°μ½λ μ΄ν°
silvercoding.tistory.com
λ΄λΆμ μΌλ‘ λμκ°λ κ² νμ ν·κ°λ €μ λ³΄κ³ μ€κΈ°
from functools import wraps
def coroutine(func):
'''Decorator run until yield'''
@wraps(func)
def primer(*args, **kwargs):
gen = func(*args, **kwargs)
next(gen)
return gen
return primer
μ λλ μ΄ν°λ₯Ό μ¬μ©ν λ μ²μμ nextλ₯Ό νΈμΆνμ§ μκ³ λ°λ‘ sendλ‘ κ°μ 보λ΄λ©΄ μ€λ₯κ° λ¬λ€. μ΄λ²μλ μ λ°μ½λ μ΄ν°λ₯Ό μ¬μ©νμ¬ λ°λ‘ κ°μ μ μ‘νλλ‘ λ§λ λ€.
@coroutine
def sumer():
total = 0
term = 0
while True:
term = yield total
total += term
su = sumer()
λ°μ½λ μ΄ν° @coroutineμ μμ±ν΄ μ£Όκ³ , κ°μ²΄ suλ₯Ό μμ±νμλ€.
print('EX2-1 - ', su.send(100))
print('EX2-2 - ', su.send(40))
print('EX2-3 - ', su.send(60))
EX2-1 - 100
EX2-2 - 140
EX2-3 - 200
λ°μ½λ μ΄ν°λ‘ μΈν΄ nextκ° νΈμΆλμκ³ , yieldμμ λ©μΆμ΄ μλ μνμ΄λ€. μ΄ μνμμ sendλ‘ 100μ μ μ‘νλ©΄ termμ 100μ΄ λ€μ΄κ°κ³ , totalμ 0+100=100μ΄ λκ³ , λ€μ yieldμμ totalμ΄ λ°νλκ³ λ©μΆλ€. κ·Έλ€μ sendλ‘ 40μ μ μ‘νλ©΄ termμ 40μ΄ λ€μ΄κ°κ³ , total=100+40=140μ΄ λμ΄ λ€μ yieldλ₯Ό λ§λ λκΉμ§ whileλ¬Έμ΄ λμ totalμ λ°ννκ³ , λ©μΆλ€. 60λ λ§μ°¬κ°μ§λ‘ λμκ°μ 200μ΄ λ°νλλ κ²μ λ³Ό μ μλ€.
- μ½λ£¨ν΄ μμ 3 (μμΈ μ²λ¦¬)
class SampleException(Exception):
'''μ€λͺ
μ μ¬μ©ν μμΈ μ ν'''
def coroutine_except():
print('>> coroutine started')
try:
while True:
try:
x = yield
except SampleException:
print('-> SampleException handled. Continuing..')
else:
print('-> coroutine received : {}'.format(x))
finally:
print('-> coroutine ending')
μμμ λ§λ€μ΄ λμ SampleExceptionμ μ΄μ©νμ¬ μμΈμ²λ¦¬λ₯Ό ν΄μ€λ€.
exe_co = coroutine_except()
κ°μ²΄ μμ±
print('EX3-1 - ', next(exe_co))
print('EX3-2 - ', exe_co.send(10))
print('EX3-3 - ', exe_co.send(100))
print('EX3-4 - ', exe_co.throw(SampleException))
print('EX3-5 - ', exe_co.send(1000))
print('EX3-6 - ', exe_co.close()) # GEN_CLOSED
print('EX3-7 - ', exe_co.send(10)) # μλ¬
>> coroutine started
EX3-1 - None
-> coroutine received : 10
EX3-2 - None
-> coroutine received : 100
EX3-3 - None
-> SampleException handled. Continuing..
EX3-4 - None
-> coroutine received : 1000
EX3-5 - None
-> coroutine ending
EX3-6 - None
Traceback (most recent call last):
File "c:/Users/./Desktop/python_high/chapter06_02.py", line 146, in <module>
print('EX3-7 - ', exe_co.send(10)) # μλ¬
StopIteration
EX3-4 μμ throw()λ₯Ό μ¬μ©νμ¬ μμΈμ²λ¦¬λ₯Ό ν μ μλ€. μμΈλ₯Ό μ‘κ³ λ€μ yieldλ‘ κ°μ Noneμ λ°ννκ³ λ©μΆμ΄ μλ κ²μ λ³Ό μ μλ€. κ·Έλμ λ€μ sendλ‘ κ°μ μ μ‘ν΄λ λμμ νκ³ , μ λλ μ΄νΈλ₯Ό μμ λλ΄κ³ μΆλ€λ©΄ close()λ₯Ό μ¬μ©νλ©΄ λλ€. close()λ₯Ό νΈμΆ ν ν , sendλ‘ κ°μ μ μ‘νλ €κ³ νλ©΄ μ€λ₯κ° λλ κ²μ μ μ μλ€.
- μ½λ£¨ν΄ μμ 4 (return)
def averager_re():
total = 0.0
cnt = 0
avg = None
while True:
term = yield
if term is None:
break
total += term
cnt += 1
avg = total / cnt
return 'Average : {}'.format(avg)
avger2 = averager_re()
κ°μΌλ‘ Noneμ λ³΄λΌ λκΉμ§ whileλ¬Έμ΄ μ€νλλλ‘ νκ³ , 보λ΄λ κ°μ λͺ¨λ λν΄μ νκ· μ λ΄μ£Όλ ν¨μμ΄λ€.
next(avger2)
avger2.send(10)
avger2.send(30)
avger2.send(50)
μμ κ°μ΄ κ°μ μ λ¬ν΄μ€λ€.
try:
avger2.send(None)
except StopIteration as e:
print('EX4-1 - ', e.value)
EX4-1 - Average : 30.0
Noneμ μ μ‘νμ¬ whileλ¬Έμμ νμΆνκ³ , μμΈμ²λ¦¬λ‘ ν¨μμ λ¦¬ν΄ κ°μ λ°μ μ μλ€.
- μ½λ£¨ν΄ μμ 4 (yield from) (3.7 -> await)
: μ€μ²© μ½λ£¨ν΄ μ²λ¦¬
(1) yield from λ―Έμ¬μ©
def gen1():
for x in 'AB':
yield x
for y in range(1, 4):
yield y
μ λλ μ΄ν° ν¨μλ₯Ό μμ±ν΄ μ€λ€.
t1 = gen1()
print('EX5-1 - ', next(t1))
print('EX5-2 - ', next(t1))
print('EX5-3 - ', next(t1))
print('EX5-4 - ', next(t1))
print('EX5-5 - ', next(t1))
print('EX5-6 - ', next(t1)) # StopIteration
EX5-1 - A
EX5-2 - B
EX5-3 - 1
EX5-4 - 2
EX5-5 - 3
Traceback (most recent call last):
File "c:/Users/./Desktop/python_high/chapter06_02.py", line 198, in <module>
print('EX5-6 - ', next(t1)) # StopIteration
StopIteration
μμμ ν΄μλ κ² μ²λΌ nextλ₯Ό νΈμΆνμ λ λ μ΄μ λ§λ yieldκ° μ‘΄μ¬νμ§ μλλ€λ©΄ Stopiteration μμΈκ° λκ² λλ€.
t2 = gen1()
print('EX5-7 - ', list(t2))
EX5-7 - ['A', 'B', 1, 2, 3]
μ΄λ κ² λ¦¬μ€νΈ κ°μ²΄λ‘ λ°μμ€ μλ μλ€.
(2) yield from μ¬μ©
def gen2():
yield from 'AB'
yield from range(1, 4)
μ΄μ κ°μ΄ yield fromμ μ¬μ©νλ©΄ μμ μμ μ²λΌ forλ¬Έμ μ¬μ©νμ§ μμλ λκ³ , κ°λ¨νκ² λ μ€λ‘ μμ±ν μ μλ€.
t3 = gen2()
print('EX6-1 - ', next(t3))
print('EX6-2 - ', next(t3))
print('EX6-3 - ', next(t3))
print('EX6-4 - ', next(t3))
print('EX6-5 - ', next(t3))
print('EX5-6 - ', next(t3)) # StopIteration
EX6-1 - A
EX6-2 - B
EX6-3 - 1
EX6-4 - 2
EX6-5 - 3
Traceback (most recent call last):
File "c:/Users/sooki/Desktop/python_high/chapter06_02.py", line 217, in <module>
print('EX5-6 - ', next(t3)) # StopIteration
StopIteration
(1)λ² μμ μ λκ°μ΄ λμ€λ κ²μ λ³Ό μ μλ€.
t4 = gen2()
print('EX6-7 - ', list(t4))
EX6-7 - ['A', 'B', 1, 2, 3]
listλ λ§μ°¬κ°μ§λ‘ λμΌνκ² λμ¨λ€.
* yield from μμ +1
def gen3_sub():
print('Sub coroutine')
x = yield 10
print('Recv: ', str(x))
x = yield 100
print('Recv: ', str(x))
def gen4_main():
yield from gen3_sub()
μμ κ°μ΄ sub coroutineμΌλ‘ ν¨μλ₯Ό μ μΈν΄ λκ³ , main coroutineμμ yield from μΌλ‘ μμ μ ν΄μ€ μ μλ€.
t5 = gen4_main()
print('EX7-1 - ', next(t5))
print('EX7-2 - ', t5.send(7))
print('EX7-3 - ', t5.send(77)) # μ€λ₯
Sub coroutine
EX7-1 - 10
Recv: 7
EX7-2 - 100
Recv: 77
Traceback (most recent call last):
File "c:/Users/sooki/Desktop/python_high/chapter06_02.py", line 247, in <module>
print('EX7-2 - ', t5.send(77))
StopIteration
'νλ‘κ·Έλλ° μΈμ΄ > Python' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[python μ¬ν] 15. Asyncio, async await (0) | 2021.07.24 |
---|---|
[python μ¬ν] 14. Future λμμ±/ λΉλκΈ° μμ μ€ν/ ThreadPoolExecutor, ProcessPoolExecutor (0) | 2021.07.23 |
[python μ¬ν] 12. λ΄λΆ iter ν¨μ, μ λλ μ΄ν°(Generator) (0) | 2021.07.17 |
[python μ¬ν] 11. ν΄λμ€ Getter, Setter, μΆμν΄λμ€ , class ABC (0) | 2021.07.14 |
[python μ¬ν] 10. copy & deep copy (0) | 2021.07.10 |