파이썬의 심화 개념들을 더 자세히 설명해드릴게요. 각 개념별로 실제 사용 사례와 함께 자세히 알아보겠습니다!
1. 파이썬의 특별한 컬렉션들 📦
리스트(List) 고급 테크닉
numbers = [1, 2, 3, 4, 5]
# 슬라이싱 상세 설명
print(numbers[1:4]) # 인덱스 1부터 3까지
print(numbers[::2]) # 처음부터 끝까지 2칸씩
print(numbers[::-1]) # 역순으로 전체
# 리스트 컴프리헨션 (List Comprehension)
# 기존 방식
squares = []
for x in range(10):
if x % 2 == 0:
squares.append(x**2)
# 컴프리헨션 방식 (더 파이썬스러운 방식)
squares = [x**2 for x in range(10) if x % 2 == 0]
딕셔너리(Dictionary) 심화
from collections import defaultdict, Counter
# defaultdict 사용 예시
# 일반 딕셔너리의 경우
normal_dict = {}
words = ['apple', 'banana', 'apple', 'cherry']
for word in words:
if word not in normal_dict:
normal_dict[word] = 0
normal_dict[word] += 1
# defaultdict 사용 시 - 훨씬 간단!
word_count = defaultdict(int)
for word in words:
word_count[word] += 1 # 키가 없어도 자동으로 0으로 초기화
# Counter 클래스 활용
inventory = Counter(['사과', '바나나', '사과', '오렌지', '바나나', '사과'])
print(inventory['사과']) # 3 출력
print(inventory.most_common(2)) # [('사과', 3), ('바나나', 2)]
2. 함수형 프로그래밍의 강력함 🎯
데코레이터 상세 설명
def login_required(func):
"""로그인 상태를 체크하는 데코레이터"""
def wrapper(*args, **kwargs):
if not is_logged_in(): # 로그인 상태 체크
raise Exception("로그인이 필요합니다!")
return func(*args, **kwargs)
return wrapper
def timer(func):
"""함수 실행 시간을 측정하는 데코레이터"""
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} 함수 실행 시간: {end - start:.2f}초")
return result
return wrapper
# 데코레이터 사용 예시
@login_required
@timer
def get_user_data(user_id):
# 데이터베이스에서 사용자 정보를 가져오는 무거운 작업
return {"id": user_id, "name": "홍길동"}
map, filter, reduce 상세 활용
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# map: 모든 요소에 함수 적용
def double(x):
return x * 2
doubled = list(map(double, numbers)) # [2, 4, 6, 8, 10]
# filter: 조건에 맞는 요소만 필터링
def is_even(x):
return x % 2 == 0
evens = list(filter(is_even, numbers)) # [2, 4]
# reduce: 요소들을 하나로 줄이기
def add(x, y):
return x + y
total = reduce(add, numbers) # 15 (1+2+3+4+5)
# 람다로 더 간단하게!
doubled = list(map(lambda x: x * 2, numbers))
evens = list(filter(lambda x: x % 2 == 0, numbers))
total = reduce(lambda x, y: x + y, numbers)
3. 객체지향 프로그래밍 심화 🏗️
클래스 메서드와 스태틱 메서드
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def from_string(cls, date_string):
"""문자열로부터 날짜 객체 생성"""
year, month, day = map(int, date_string.split('-'))
return cls(year, month, day)
@staticmethod
def is_valid_date(date_string):
"""날짜 문자열이 유효한지 검증"""
try:
year, month, day = map(int, date_string.split('-'))
return 1 <= month <= 12 and 1 <= day <= 31
except:
return False
# 사용 예시
date1 = Date(2024, 3, 14) # 일반적인 생성
date2 = Date.from_string('2024-03-14') # 클래스 메서드로 생성
is_valid = Date.is_valid_date('2024-03-14') # 정적 메서드 사용
프로퍼티와 접근제어
class BankAccount:
def __init__(self, initial_balance):
self._balance = initial_balance # protected
self.__transactions = [] # private
@property
def balance(self):
"""잔액 조회"""
return self._balance
@balance.setter
def balance(self, amount):
"""잔액 변경"""
if amount < 0:
raise ValueError("잔액은 음수가 될 수 없습니다")
self.__transactions.append(amount - self._balance)
self._balance = amount
def get_transaction_history(self):
"""거래 내역 조회"""
return self.__transactions.copy() # 복사본 반환
# 사용 예시
account = BankAccount(1000)
print(account.balance) # 프로퍼티로 접근
account.balance = 2000 # setter 호출
4. 비동기 프로그래밍 실전 ⚡
async/await 상세 예제
import asyncio
import aiohttp
import time
async def fetch_pokemon(session, pokemon_id):
"""포켓몬 정보를 비동기로 가져오기"""
url = f"https://pokeapi.co/api/v2/pokemon/{pokemon_id}"
async with session.get(url) as response:
return await response.json()
async def main():
async with aiohttp.ClientSession() as session:
# 여러 포켓몬 정보를 동시에 가져오기
pokemon_ids = range(1, 11)
tasks = [fetch_pokemon(session, pid) for pid in pokemon_ids]
results = await asyncio.gather(*tasks)
for pokemon in results:
print(f"포켓몬: {pokemon['name']}")
# 실행 시간 측정
start = time.time()
asyncio.run(main())
end = time.time()
print(f"실행 시간: {end - start:.2f}초")
5. 고급 에러 처리와 디버깅 🔍
커스텀 예외 체인
class ValidationError(Exception):
"""데이터 검증 실패 시 발생하는 예외"""
pass
class DatabaseError(Exception):
"""데이터베이스 작업 실패 시 발생하는 예외"""
pass
def save_user_data(user_dict):
try:
# 데이터 검증
if 'name' not in user_dict:
raise ValidationError("이름은 필수입니다")
# 데이터베이스 저장 시도
try:
save_to_database(user_dict)
except Exception as e:
raise DatabaseError("데이터 저장 실패") from e
except (ValidationError, DatabaseError) as e:
print(f"에러 발생: {e}")
print(f"원인: {e.__cause__}") # 원인 예외 출력
6. 실전 프로젝트: 데이터 분석 파이프라인 💪
import pandas as pd
import numpy as np
from typing import Optional, Dict, List
class DataAnalyzer:
"""데이터 분석을 위한 파이프라인 클래스"""
def __init__(self, data: pd.DataFrame):
self.data = data
self.original_data = data.copy() # 원본 데이터 보관
def clean_data(self) -> 'DataAnalyzer':
"""데이터 클렌징"""
# 결측치 처리
self.data = self.data.fillna(self.data.mean())
# 이상치 제거 (IQR 방식)
Q1 = self.data.quantile(0.25)
Q3 = self.data.quantile(0.75)
IQR = Q3 - Q1
self.data = self.data[~((self.data < (Q1 - 1.5 * IQR)) |
(self.data > (Q3 + 1.5 * IQR)))]
return self
def analyze(self) -> Dict:
"""기본 통계 분석 수행"""
return {
'basic_stats': self.data.describe(),
'correlations': self.data.corr(),
'missing_ratio': self.data.isnull().sum() / len(self.data)
}
@timer # 위에서 정의한 타이머 데코레이터 사용
def generate_report(self) -> Dict:
"""분석 리포트 생성"""
return {
'summary': self.analyze(),
'data_shape': self.data.shape,
'data_types': self.data.dtypes.to_dict()
}
# 사용 예시
data = pd.read_csv('sample_data.csv')
analyzer = DataAnalyzer(data)
report = (analyzer
.clean_data()
.generate_report())
성능 최적화 상세 팁 ⚡
1. 제너레이터 활용
def read_large_file(file_path: str, chunk_size: int = 1024):
"""대용량 파일을 조금씩 읽는 제너레이터"""
with open(file_path, 'r') as file:
while True:
data = file.read(chunk_size)
if not data:
break
yield data
# 메모리 효율적인 파일 처리
for chunk in read_large_file('big_file.txt'):
process_data(chunk)
2. NumPy 최적화
import numpy as np
# 리스트 연산 vs NumPy 연산 비교
def list_operation():
lst = list(range(1000000))
return [x ** 2 for x in lst]
def numpy_operation():
arr = np.arange(1000000)
return arr ** 2
# 성능 비교
import time
start = time.time()
list_result = list_operation()
print(f"리스트 연산 시간: {time.time() - start:.2f}초")
start = time.time()
numpy_result = numpy_operation()
print(f"NumPy 연산 시간: {time.time() - start:.2f}초")
마치며 🎁
이러한 고급 기능들을 마스터하면 더 효율적이고 견고한 코드를 작성할 수 있습니다. 특히 실전에서는 이런 기능들을 조합해서 사용하는 경우가 많답니다!
- 데이터 처리할 때는 NumPy와 Pandas를
- 웹 개발할 때는 비동기 프로그래밍을
- 큰 프로젝트에서는 객체지향 패턴을
- 유틸리티 개발할 때는 함수형 프로그래밍을
상황에 맞게 적절히 활용해보세요! 😊
더 깊이 있는 내용이나 특정 주제에 대해 궁금하신 점이 있다면 댓글로 남겨주세요!
728x90