next(), yield, __iter__
class splitter :
def __init__(self,text) :
self._idx = 0
self._text = text.split(' ')
def __next__(self) :
print('called __next__)
try :
word = self.text[self._idx]
except IndexError :
raise StopIteration('Stopped Itteration.')
self._idx += 1
return word
def __repr__(self) :
return 'word split(%s)' % (self._text)
word_split = splitter('do today what you can')
print(word_split) # word split([do, today, what, you, can])
print(next(word_split) # called __next__ do
print(next(word_split) # called __next__ today
class splitter() :
def __init__(self,text) :
self._text = text.split(' ')
def __iter__(self) :
for word in self._text :
yield word # 제너레이터
def __repr__(self) :
return 'word split(%s)' % (self._text)
word_gene = splitter('do today')
wt = iter(wg) # 이터함수를 따로 설정
print(wt) # genertor object ...
print(word_gene) # word split(['do','today'])
print(next(wt)) # do
print(next(wt)) # today
병행성 : 한컴퓨터가 여러 일을 동시에 수행 -> 단일 프로그램 안에서 여러일을 쉽게 수행
병렬성 : 여러 컴퓨터가 여러 작업을 동시에 수행 -> 속도
def generator1() :
print('strat')
yield 'A point' # 첫 next 사용시 여기서 대기
print('continue')
yield 'B point' # 두번째 next 시 여기까지 출력 a 부터
print('end')
temp = generator1()
print(next(temp)) # start, A point
print(next(temp)) # continue, B point
print(next(temp)) # end , StopIteration 에러 발생
temp2 = [x * 3 for x in generator_1()] # ['A point A point A point ', 'B point B point B point '] yield 부분이 x 로 들어감
temp3 = (x * 3 for x in generator_1()) # <generator object <genexpr> at 0x11fa1f440>
for i in temp3:
print(i) # Apoint,Bpoint 3회 반복되고 출력 start부터 end 까지
함수를 실행 중간에 멈췄다가 다시 실행을 재개 할 수 있는 함수
반드시 시작(next) 하고 사용해야함
- 코루틴 : 단일(싱글) 스레드, 스텍을 기반으로 동작하는 비동기 작업
- 쓰레드 : os 관리, CPU 코어에서 실시간 ,시분할 비동기 작업 -> 멀티쓰레드
- yield : 메인과 서브가 상호작용 : 코루텐 제어, 상태, 양방향 전송 # send 루틴을 통해
- 서브루틴 : 메인루틴 호출 -> 서브루틴에서 수행 (흐름제어)
- 코루틴 : 루틴 실행 중지 -> 동시성 프로그래밍
- 코루틴 : 쓰레드에 비해 오버헤드 감소
- 스레드 : 싱글스레드 -> 멀티스레드 -> 복잡 -> 공유되는 자원 -> 교착 상태 발생 가능성, 컨텍스트 스위칭 비용 발생, 자원 소비 가능성 증가 오히려 싱글스레드가 빠를수도 있음
* def -> async, yield -> await : python 3.5 이상부터 사용 가능
# 서브 루틴 (만들기)
def coroutine1() :
print('coroutine start.')
i = yield # 중요!!!
print('coroutine received : {}'.format(i))
# 메인 루틴
cr1 = coroutine1()
print(cr1, type(cr1)) # generator object...,<class 'generator'>
# yield 지점까지 서브루틴 수행
next(cr1) # coroutine start
# 전달한 값이 없기에 none 출력
next(cr1) # coroutine received : None + 당연히 stopiteration 발생
# 위를 주석처리하고 첫 start 상태에서
# 값 전송 send()
cr1.send(1)
next(cr1) # coroutine received : 1 + 당연히 stopiteration 발생
# start 를 하지 않은 상태에서 바로 send 값을 주면 yield 에 도달하지 않은 상태기에 오류발생, 타입에러
# 상태값 출력 가능
# from inspect import getgeneratorstate
# GEN_CREATED : 처음 대기 상태
# GEN_RUNNING : 실행 상태
# GEN_SUSPENDED : yield 대기 상태
# GEN_CLOSED : 실행 완료 상태
from inspect import getgeneratorstate # 인세펙터 모듈 사용
def coroutine2(x) :
print('started : 'x)
y = yield x # 1 포인트
print('received : ',y)
z = yield x + y # x+y 값 반환 보려면 반환시켜야댐 # 2 포인트
print('received : ',z)
cr3 = coroutine2(10)
print(getgeneratorstate(cr3)) # 현재상태 : GEN_CREATED 출력
next(cr3)
print(getgeneratorstate(cr3)) # started : 10 ,GEN_SUSPENDED, 현재 1번포인트 대기
# 2번째 포인트의 yield 반환 x+y 값을 쓰고싶다면?
result = cr3.send(100) # 보내느 값을 반환 받는 변수를 찾아줘야한다!!!
# send 에대한 received 100 먼저 출력후
print(result) # 110 출력됨
# 3. 두 번째 send 호출
try:
result = cr3.send(200) # 세 번째 yield에서 반환된 값 (없으므로 종료)
print(f'Returned by yield: {result}')
except StopIteration:
print('Coroutine finished') # 코루틴 종료 처리
print(getgeneratorstate(cr3)) # GEN_CLOSED
# stopiteration 자동처리
# 중첩 코루틴
def generator1() :
for x in 'AB' :
yield x
for y in range(1,4) :
yield y
t1 = generator1()
print(next(t1)) # A
print(next(t1)) # B
print(next(t1)) # 1
print(next(t1)) # 2
print(next(t1)) # 3
t2 = generator1() # 이미 다소진했기에 전부 다보려면 새로 출력
print(list(t2)) # ['A,'B','1','2','3'] #
def generator2() : # 위와 똑같은 제너레이터 이다
yield from 'AB'
yield from range(1,4)
---
- 비동기 작업 실행 (<-> 동기 : 순차적으로 실행)
- 지연시간 CPU 및 리소스 낭비 방지 -> Network(file) I/O 관련 작업 -> 동시성 활용 권장
- concurrent.Futures : 잘 만들어 져 있느 모듈 사용
import time
from cocurrent import futures
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, wait, as_completed
work_list =[1000,10000,100000,1000000]
# 누적 합계 함수 제네레이터 활용
def sum_generator(n) :
return sum(n for n in range(1,n+1))
def main () :
worker = min(10,len(work_list))
start = time.time()
# wait
# 결과
# ProcessPoolExecutor, ThreadPoolExecutor (순차,병렬)
with futures.ThreadPoolExecutor() as executor :
# map -> 작업 순서 유지, 즉시 실행
result = executor.map(sum_generator,work_list)
# wait 결과 출력
result = wait(futures_list, timeout=7) # 시간을 정할수 있고 제어 할 수있다.
end = time.time() - start
msg = '\n Result -> {} Time : {:.2f}s'
# as completed
print(msg.format(list(result),end))
as_completed 결과 출력 # 먼저 끝나는것 부터 하나씩 출력된다
for future in as_completed(futures_list):
result = future.result()
done = future.done()
cancelled = future.cancelled
# future 결과 확인
print('Future Result : {}, Done : {}'.format(result, done))
print('Future Cancelled : {}'.format(cancelled))
if __name__ == '__main__' :
main()
## from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, wait, as_completed