next()와 제너레이터 표현식

2024. 12. 9. 10:30·파이썬/Basic
반응형

소개

Python의 next()와 제너레이터 표현식은 메모리 효율적인 데이터 처리를 위한 강력한 도구입니다. 이번 글에서는 이들의 사용법과 실제 활용 사례를 살펴보겠습니다.

next() 함수 이해하기

기본 사용법

# 간단한 이터레이터 생성
numbers = iter([1, 2, 3])

# next() 사용
first = next(numbers)  # 1
second = next(numbers)  # 2
third = next(numbers)  # 3

# StopIteration 예외 발생
try:
    next(numbers)  # StopIteration 발생
except StopIteration:
    print("더 이상 요소가 없습니다")

next()의 기본값 활용

numbers = iter([1, 2, 3])

# 기본값 설정
value = next(numbers, -1)  # 1
value = next(numbers, -1)  # 2
value = next(numbers, -1)  # 3
value = next(numbers, -1)  # -1 (기본값 반환)
장점 단점
메모리 효율적 이전 값 재접근 불가
지연 평가 지원 인덱스 접근 불가
기본값 설정 가능 길이 계산 어려움
직관적인 사용법 반복 후 재사용 불가

제너레이터 표현식

기본 문법

# 리스트 컴프리헨션
squares_list = [x**2 for x in range(1000000)]  # 메모리에 모든 값 저장

# 제너레이터 표현식
squares_gen = (x**2 for x in range(1000000))  # 필요할 때만 값 생성

활용

# 파일 읽기
def read_large_file(file_path):
    with open(file_path) as f:
        return (line.strip() for line in f)

# 데이터 필터링
numbers = (x for x in range(1000) if x % 2 == 0)

# 데이터 변환
names = ['Alice', 'Bob', 'Charlie']
upper_names = (name.upper() for name in names)

실전 활용

대용량 데이터 처리

def process_large_dataset(data_path):
    # 파일에서 데이터 읽기
    lines = (line.strip() for line in open(data_path))

    # 데이터 필터링 및 변환
    processed = (
        int(line) 
        for line in lines 
        if line.isdigit()
    )

    # 청크 단위 처리
    chunk = []
    chunk_size = 1000

    for num in processed:
        chunk.append(num)
        if len(chunk) == chunk_size:
            process_chunk(chunk)
            chunk = []

메모리 효율적인 데이터 변환

class DataTransformer:
    def __init__(self, data):
        self.data = data

    def transform(self):
        # 단계별 변환 파이프라인
        return (
            self._process(item)
            for item in self.data
            if self._validate(item)
        )

    def _validate(self, item):
        return bool(item)

    def _process(self, item):
        return item.upper()

# 사용 예시
transformer = DataTransformer(['a', 'b', 'c'])
result = transformer.transform()
first = next(result)  # 'A'

무한 시퀀스 생성

def infinite_sequence():
    num = 0
    while True:
        yield num
        num += 1

# 피보나치 수열
def fibonacci_generator():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

# 사용 예시
numbers = infinite_sequence()
first_five = [next(numbers) for _ in range(5)]  # [0, 1, 2, 3, 4]

데이터 파이프라인 구축

def data_pipeline():
    # 데이터 소스
    raw_data = (x for x in range(1000))

    # 필터링
    filtered = (
        x for x in raw_data
        if x % 2 == 0
    )

    # 변환
    transformed = (
        x * 2 for x in filtered
    )

    # 그룹화
    groups = (
        (i, list(group))
        for i, group in itertools.groupby(transformed, key=lambda x: x // 10)
    )

    return groups

커스텀 이터레이터

class DataStream:
    def __init__(self, start=0, step=1):
        self.current = start
        self.step = step

    def __iter__(self):
        return self

    def __next__(self):
        value = self.current
        self.current += self.step
        return value

# 사용 예시
stream = DataStream(start=5, step=2)
values = [next(stream) for _ in range(5)]  # [5, 7, 9, 11, 13]

성능 최적화 팁

메모리 사용량 비교

import sys

# 리스트 컴프리헨션
numbers_list = [x for x in range(1000000)]
print(sys.getsizeof(numbers_list))  # 큰 메모리 사용

# 제너레이터 표현식
numbers_gen = (x for x in range(1000000))
print(sys.getsizeof(numbers_gen))  # 작은 메모리 사용

실행 시간 최적화

from itertools import islice

def optimize_processing():
    # 전체 데이터를 한 번에 처리하는 대신
    # 청크 단위로 처리
    data = (x for x in range(1000000))
    chunk_size = 1000

    while True:
        chunk = list(islice(data, chunk_size))
        if not chunk:
            break
        process_chunk(chunk)

주의사항과 팁

이터레이터 소진 주의

numbers = (x for x in range(5))
list(numbers)  # [0, 1, 2, 3, 4]
list(numbers)  # [] (이미 소진됨)

# 재사용이 필요한 경우
def get_numbers():
    return (x for x in range(5))

list(get_numbers())  # [0, 1, 2, 3, 4]
list(get_numbers())  # [0, 1, 2, 3, 4]

디버깅 팁

def debug_generator(gen):
    for value in gen:
        print(f"Debug: {value}")
        yield value

# 사용 예시
numbers = (x for x in range(5))
debugged = debug_generator(numbers)
list(debugged)  # 각 값을 출력하면서 처리

마치며

next()와 제너레이터 표현식은 Python에서 메모리 효율적인 프로그래밍을 가능하게 하는 강력한 도구입니다. 특히 대용량 데이터 처리나 스트리밍 데이터를 다룰 때 매우 유용합니다. 상황에 맞게 적절히 활용하면 프로그램의 성능을 크게 향상시킬 수 있습니다.

저작자표시 비영리 변경금지 (새창열림)

'파이썬 > Basic' 카테고리의 다른 글

함수 하나로 여러 가지 처리하기? Python 오버로딩  (2) 2024.12.27
자료구조 : deque, Queue, heapq  (0) 2024.12.10
순환 참조(Circular Import) 이해하기와 해결 방법  (2) 2024.12.06
파이썬에서 디자인 패턴 적용하기  (8) 2024.10.24
다양한 이미지 확장자와 확장자 변경하기  (6) 2024.10.23
'파이썬/Basic' 카테고리의 다른 글
  • 함수 하나로 여러 가지 처리하기? Python 오버로딩
  • 자료구조 : deque, Queue, heapq
  • 순환 참조(Circular Import) 이해하기와 해결 방법
  • 파이썬에서 디자인 패턴 적용하기
코샵
코샵
나의 코딩 일기장
    반응형
  • 코샵
    끄적끄적 코딩 공방
    코샵
    • 분류 전체보기 (725)
      • 스마트팜 (0)
      • 상품 추천 (223)
      • MongoDB (4)
      • 하드웨어 (17)
      • 일기장 (4)
      • 파이썬 (130)
        • Basic (41)
        • OpenCV (8)
        • Pandas (15)
        • PyQT (3)
        • SBC(Single Board Computer) (1)
        • 크롤링 (14)
        • Fast API (29)
        • Package (6)
      • Unity (138)
        • Tip (41)
        • Project (1)
        • Design Pattern (8)
        • Firebase (6)
        • Asset (2)
      • Linux (4)
      • C# (97)
        • Algorithm (11)
        • Window (7)
      • TypeScript (51)
        • CSS (10)
      • Git (11)
      • SQL (5)
      • Flutter (10)
        • Tip (1)
      • System (1)
      • BaekJoon (6)
      • Portfolio (2)
      • MacOS (1)
      • 유틸리티 (1)
      • 서비스 (6)
      • 자동화 (3)
      • Hobby (10)
        • 물생활 (10)
        • 식집사 (0)
  • 인기 글

  • 태그

    리뷰관리
    스크립트 실행 순서
    learntocode
    ipcamera
    상품 리뷰 크롤링
    믈레코비타멸균우유
    스마트스토어리뷰
    codingcommunity
    cv2
    appdevelopment
    codingtips
    programmerlife
    programming101
    카페24리뷰
    유니티
    셀레니움
    리스트
    스크립트 실행
    devlife
    Python
    list
    리뷰이관
    파이썬
    카페24리뷰이관
    rtsp
    unity
    C#
    라떼우유
    쇼핑몰리뷰
    긴유통기한우유
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코샵
next()와 제너레이터 표현식
상단으로

티스토리툴바