코드 결과
def generate_daily_intervals(self, *, start_date: datetime, end_date: datetime):
delta = timedelta(days=1)
while start_date <= end_date:
yield start_date
start_date += delta
코드 설명
Python에서 제너레이터 함수(Generator Function)를 활용해, 특정 기간 동안 일 단위로 날짜를 순회하는 기능을 구현한 예시임.
함수 정의 시그니처
def generate_daily_intervals(self, *, start_date: datetime, end_date: datetime):
...
1. self
클래스 메서드(인스턴스 메서드) 안에서 정의됨.
메서드를 호출할 때 인스턴스 자신이 self로 전달됨.
2. * (별표)
키워드 전용 인자(Keyword-only Argument)를 지정하기 위해 사용됨.
즉, generate_daily_intervals 함수를 호출할 때, start_date와 end_date는 반드시 키워드 인자로 제공해야 함.
예를 들면, obj.generate_daily_intervals(start_date=my_start, end_date=my_end)
3. start_date: datetime, end_date: datetime
Python 3의 타이핑 힌트(Type Hint) 문법임.
이 코드만으로는 강제성은 없지만, IDE 또는 정적 분석기(Mypy 등)를 통해 타입 검증을 할 수 있음.
제너레이터 함수
while start_date <= end_date:
yield start_date
start_date += delta
1. 제너레이터(Generator)
yield 키워드를 사용하면, 함수가 일반적인 함수와 달리 값을 하나씩 반환하고, 해당 지점에서 상태(state)를 유지한 채 일시 중단됨.
이후 다음 호출(이터레이션) 때 중단 지점부터 재개됨.
이 구조를 통해 매번 메모리에 모든 값을 올리지 않고도 순차적으로 값을 "생성"해낼 수 있는 장점이 있음.
즉, 이 함수는 호출 시점에 한 번에 모든 날짜 리스트를 만들지 않고, 필요한 날짜를 그때그때 순회(iteration)를 통해 반환함.
날짜 간격 계산
delta = timedelta(days=1)
datetime.timedelta(days=1)는 하루(24시간)의 시간 간격을 나타내는 객체임.
이후 start_date += delta를 통해, start_date를 하루씩 증가시킴.
로직의 흐름
1. 초기화
start_date, end_date, 그리고 하루 간격 delta가 설정됨
2. 반복 조건
while start_date <= end_date
start_date가 end_date를 초과하기 전까지 반복
3. yield
현재 start_date를 반환(생성)
제너레이터의 핵심은 이 시점에서 함수의 실행이 일시중단되고, 호출 측(이터레이터)에서 next()를 호출하면 다음 줄(다음 반복)부터 재개함.
4. 증가
start_date += delta
start_date를 하루 증가시켜 다음 반복에서 사용
사용 예시
# 예시로, 2025년 1월 1일부터 1월 5일까지 날짜를 생성하는 경우
start = datetime(2025, 1, 1)
end = datetime(2025, 1, 5)
# 메서드가 속한 클래스 인스턴스를 가정: obj
for d in obj.generate_daily_intervals(start_date=start, end_date=end):
print(d)
# 출력:
# 2025-01-01 00:00:00
# 2025-01-02 00:00:00
# 2025-01-03 00:00:00
# 2025-01-04 00:00:00
# 2025-01-05 00:00:00
이처럼 시작 날짜부터 종료 날짜까지 1일씩 간격을 두면서 datetime 객체를 순차적으로 생성하게 됨.
정리
이 함수는 날짜 범위를 순회하기 위한 제너레이터 함수임.
yield를 사용함으로써, 반복 시점마다 날짜를 하나씩 반환하고, 메모리를 절약하면서 간단한 방법으로 일(day) 단위 날짜 목록을 얻을 수 있음.
start_date <= end_date 조건이 유지되는 동안 매 루프마다 start_date가 하루씩 증가하여, 끝 날짜를 포함해 모든 날짜가 차례로 생성됨.
키워드 전용 인자(*, start_date, end_date)와 타입 힌트를 통해, API 사용성을 명확히 하면서도, IDE나 정적 분석 도구에서 타입 검증을 더 용이하게 해줌.
이 코드 패턴은 날짜 범위 생성이 필요한 다양한 상황(예: 달력 UI 생성, 로그 분석 시 특정 기간 데이터 처리, 테스트 시 가상의 날짜 목록 생성 등)에서 간결하고 효율적으로 활용할 수 있음.
더 나은 코드 제안
아래처럼 range 기반으로 작성하면, 코드가 조금 더 간결하고 Pythonic하게 개선할 수 있음.
또한 타입 힌트, Docstring, 간단한 경계 조건 체크를 추가해서, 가독성과 안정성을 높일 수도 있음.
from datetime import datetime, timedelta
from typing import Generator
def generate_daily_intervals(
self,
*,
start_date: datetime,
end_date: datetime
) -> Generator[datetime, None, None]:
"""
Generates daily intervals (1-day increments) from `start_date` up to `end_date` (inclusive).
:param start_date: The beginning date (inclusive).
:param end_date: The ending date (inclusive).
:yield: A datetime object for each day in the range.
"""
# 간단한 경계 조건 처리 (end_date가 start_date보다 이전이면 바로 종료)
if end_date < start_date:
return
# 일 수 계산
total_days = (end_date - start_date).days
# range를 통해 0부터 total_days까지 반복 → start_date에 day_offset을 더해 각 날짜 생성
for day_offset in range(total_days + 1):
yield start_date + timedelta(days=day_offset)
이 코드가 기존 코드 대비 장점이 될 수 있는 점
1. 간결함(Pythonic)
range와 (end_date - start_date).days를 활용해, 1일씩 증가하는 로직을 한눈에 이해하기 쉬움.
2. 명확한 반환 타입
typing 모듈의 Generator를 사용해 제너레이터라는 사실과 반환 타입을 명시함으로써, IDE나 정적 분석기 사용 시 가독성과 안정성을 높임.
3. Docstring 제공
함수 사용 방법과 파라미터 설명, 동작 방식을 명확히 기술함.
4. 경계 조건 처리
end_date < start_date일 경우에는 굳이 반복할 필요가 없으므로 바로 반환하도록 처리하여, 의도치 않은 빈 루프를 방지할 수 있음.
5. 확장성
필요하다면 추가 파라미터(예: step_days=1, inclusive=True/False 등)를 쉽게 넣고, range 파라미터만 조정해서 일 단위 증가 폭을 유연하게 확장할 수 있음.
물론, 기존 while 루프 방식도 잘 동작하지만, 위와 같은 개선으로 가독성과 명확성을 조금 더 높일 수 있습니다.
'Programming Language > Python' 카테고리의 다른 글
[Python] 데이터프레임 S3 저장 함수 (0) | 2025.01.04 |
---|---|
[Python] 파이썬에서 아테나에 쿼리를 실행하는 방법 (0) | 2025.01.04 |
[Python] Avro 파일 개념 (0) | 2025.01.04 |
[Python] Parquet 파일 개념 (0) | 2025.01.04 |
[Python] 너비 우선 탐색 (0) | 2024.06.09 |