Remarks
이 글은 전문가를 위한 파이썬(Fluent Python)을 정리한 자료입니다.
reprlib.repr()
: 문자열을 잘라 생성 (default: 30자)
1. Generator
yield
키워드를 포함하는 함수는 모두 generator 함수이다.def __iter__(self): for word in self.words: yield word return
- 반복문,
next()
등을 이용하여 값을 가져올 수 있다.next()
호출 시, 함수 본체에 있는 다음yield
로 진행하며,next()
는 함수 본체가 중단된 곳에서 생성된 값을 평가한다.- 그래서 제너레이터 함수 안에 있는
return
은StopIteration
예외를 발생하게 만들 뿐이다.
- 제너레이터 함수는 함수 본체를 포함하는 제너레이터 객체를 생성한다.
- 바람직한 Sentence iterator 구현
import re import reprlib RE_WORD = re.compile("\w+") class Sentence: def __init__(self, text): self.text = text def __repr__(self): return f"Sentence({reprlib.repr(self.text)})" def __iter__(self): return (match.group() for match in RE_WORD.finditer(self.text))
- 무한 수열을 생성하는 경우에도 유용하게 사용된다.
itertools.count()
: 무한 등차수열 생성itertools.takewhile()
: 다른 제너레이터를 소비하면서 조건식(predicate)가False
가 되면 중단되는 제너레이터를 생성gen = itertools.takewhile(lambda n: n < 3, itertools.count(1, .5))
itertools.compress(it, selector_it)
:selector_it
의 해당 항목이True
일 때마다it
에서 항목을 생성itertools.accumulate(it, [func])
:func
를 적용한 결과를 첫 번째 값으로 생성하며it
를 반복하며 누적 합계를 계산itertools.accumulate([3, 2, 4, 5, 1]) itertools.accumulate([3, 2, 4, 5, 1], min) itertools.accumulate([3, 2, 4, 5, 1], max) itertools.accumulate([3, 2, 4, 5, 1], operator.mul)
itertools.chain(it1, ..., itN)
:it1
부터 나머지 반복형의 항목을 차례대로 생성>>> list(itertools.chain("ABC", range(2))) ["A", "B", "C", 0, 1] >>> list(itertools.chain.from_iterable(enumerate("ABC"))) [0, 'A', 1, 'B', 2, 'C']
itertools.zip_longest
:zip
의 longest versionitertools.groupby
: 예제 참고import itertools animals = ["duck", "eagle", "rat", "giraffe", "bear", "bat", "dolphin", "shark", "lion"] # list should be sorted by the key animals.sort(key=len) for length, group in itertools.groupby(animals, key=len): print(f"In group of length {length}: {list(group)}")
In group of length 3: ['rat', 'bat'] In group of length 4: ['duck', 'bear', 'lion'] In group of length 5: ['eagle', 'shark'] In group of length 7: ['giraffe', 'dolphin']
iter()
의 다른 사용법- 1이 나올 때까지 주사위 굴리기
# Sample until 1 is selected (1 is never printed) for roll in iter(lambda: randint(1, 6), 1): print(roll)
- 빈 줄을 발견하거나 파일의 끝에 도달할 때까지 한 줄씩 읽기
with open("mydata.txt") as fp: for line in iter(fp.readline, ""): ...
물론, 실제론 다음과 같은 방식이 더 좋다.
with open("mydata.txt") as fp: for line in fp: ...
- 1이 나올 때까지 주사위 굴리기
Appendix
- 객체를 반복하기 전에 객체가 반복형인지 명시적으로 검사하는 것은 필요하지 않다.
__iter__()
를 구현하는 객체만 반복형이라 간주하지만, 그렇지 않아도 반복가능하기 때문에 오히려 헷갈릴 수 있음
issubclass(cls, abc.Iterable)
,isinstance(ins, abc.Iterable)
- 암묵적 수치 변환
result = type(self.begin + self.step)(self.begin)
- 오차 누적을 줄이기 위해, 여러 번의 덧셈 대신 곱셈 한 번, 덧셈 한 번만 수행
result = self.begin + self.step * index
math.fsum()
을 이용하면 정밀도가 향상된다.
PREVIOUSEtc