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