- 흐름제어
병행성(Concurrency) : 한 컴퓨터가 여러 일을 동시에 수행 -> 단일 프로그램안에서 여러일을 쉽게 해결
병렬성(Parallelism) : 여러 컴퓨터가 여러 작업을 동시에 수행 -> 속도
코루틴(Coroutine) : 단일(싱글) 스레드, 스택을 기반으로 동작하는 비동기 작업
스레드 : OS 관리, cpu 코어에서 실시간, 시분할 비동기 작업 -> 멀티스레드
yield, send : 메인 <==> 서브
코루틴 제어, 상태, 양방향 전송
yield from
서브루틴 : 메인루틴에서 호출 -> 서브루틴에서 수행(흐름제어)
코루틴 : 루틴 실행 중 중지 -> 동시성 프로그래밍
코루틴 : 스레드에 비해 오버헤드 감소
스레드 : 싱글스레드 -> 멀티스레드 -> 복잡 -> 공유되는 자원 -> 교착 상태 발생 가능성, 컨텍스트 스위칭 비용 발생, 자원 소비 가능성 증가
3.5이상에서, def -> async, yield -> await
# 코루틴 Ex1
def coroutine1():
print('>>> coroutine started.')
i = yield
print('>>> coroutine received : {}'.format(i))
# 제네레이터 선언
cr1 = coroutine1()
print('제너레이터 선언:', cr1, '~', type(cr1))
# 제너레이터 선언: < generator object coroutine1 at 0x000002B8320447D8 > ~ < class 'generator' >
# 메인 루틴
# yield 지점 까지 서브루틴 수행
next(cr1) # "i = yield"까지 실행됨, 그래서 첫번째 print 출력됨
# >>> coroutine started.
# 기본 전달 값 None
# next(cr1) # yield 한개라서 예외발생함
# >>> coroutine received : None
# Traceback (most recent call last):
# next(cr1)
# StopIteration
# 값 전송
print('--------------------')
cr1.send(100) # yield 에서 대기중일때만 send 가능.
# >>> coroutine received : 100
# Traceback (most recent call last):
# cr1.send(100)
# StopIteration
잘못된 사용 예시
# 잘못된 사용
cr2 = coroutine1()
cr2.send(100) # 예외 발생, yield 지점이 아닌데, send 호출시 오류 발생.
# ----> 5 cr2.send(100) # 예외 발생
# TypeError: can't send non-None value to a just-started generator
코루틴 상태확인
# 코루틴 Ex2
# GEN_CREATED : 처음 대기 상태
# GEN_RUNNING : 실행 상태
# GEN_SUSPENDED : yield 대기 상태, 이때 send 가능. 제일 중요한 상태.
# 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))
cr3 = coroutine2(10)
from inspect import getgeneratorstate
print(getgeneratorstate(cr3))
# GEN_CREATED
print(next(cr3))
# >>> coroutine started : 10
# 10
print(getgeneratorstate(cr3))
# GEN_SUSPENDED
print(cr3.send(15))
# >>> coroutine received : 15
# 25
# print(cr3.send(20)) # 예외, 한번 더 호출하면 예외 발생해서 z 는 출력 안됨.
# # >>> coroutine received : 20
# # Traceback (most recent call last):
# # print(cr3.send(20)) # 예외, 한번 더 호출하면 예외 발생해서 z 는 출력 안됨.
# # StopIteration
# 코루틴 Ex3
# StopIteration 자동 처리(3.5 -> await)
# 중첩 코루틴 처리
def generator1():
for x in 'AB':
yield x
for y in range(1,4):
yield y
t1 = generator1()
print(next(t1))
print(next(t1))
print(next(t1))
print(next(t1))
print(next(t1))
# A
# B
# 1
# 2
# 3
# print(next(t1)) # 예외 발생, exception
# # Traceback (most recent call last):
# # print(next(t1))
# # StopIteration
t2 = generator1()
print(list(t2))
# ['A', 'B', 1, 2, 3]
yield from
def generator2():
yield from 'AB'
yield from range(1,4)
t3 = generator2()
print(next(t3))
print(next(t3))
print(next(t3))
print(next(t3))
print(next(t3))
# A
# B
# 1
# 2
# 3
# print(next(t3)), exception
# # Traceback (most recent call last):
# # print(next(t3))
# # StopIteration
조금 더 - 함수 객체를 리턴할지, 아니면 제너레이터 객체를 리턴할지 명확히 해야함.
def make_generator():
factor = 2
def multiplier(n):
# nonlocal factor
return factor * n # 값 변경이 없어서 nonlocal factor 선언 필요없음.
def gen():
for i in range(5):
yield multiplier(i) # 클로저를 활용한 제너레이터
return gen # 함수객체 반환
# return gen() # gen()를 리턴하면 generator 객체 생성됨/객체를 반환
# return gen 인 경우
g = make_generator()
print(list(g())) # [0, 2, 4, 6, 8]
# return gen() 인 경우
# g = make_generator()
# print(list(g)) # [0, 2, 4, 6, 8]
'Python > Intermediate' 카테고리의 다른 글
[Python] 병행성(Concurrency) - Futures(2) (0) | 2021.05.26 |
---|---|
[Python] 병행성(Concurrency)(4) - Futures(1) (0) | 2021.05.26 |
[Python] 병행성(Concurrency)(2) - generator (0) | 2021.05.25 |
[Python] 병행성(Concurrency)(1) - basic (0) | 2021.05.25 |
[Python] 일급함수(4) - Decorator (0) | 2021.05.25 |