Java 에서 오면 본능이 "모든 거 클래스에 wrap". Python 문화는 반대로 밀어 — 함수와 모듈 먼저, 진짜 state 있을 때 클래스. __init__ 외 메서드 하나, 말할 만한 인스턴스 속성 X, 메서드 호출 위해서만 인스턴스화 — 함수여야.
클래스 안 필요한 신호
(1) __init__ 외 메서드 하나만. (2) __init__ 이 변환 없이 인자 그냥 저장. (3) 클래스가 인스턴스화, 메서드 호출, 인스턴스 폐기. (4) 클래스에 state 변경 메서드 X. 넷 다 — 함수 짜. 4 중 3 — 아마 함수.
모듈이 네임스페이스
Java 에서 관련 함수 그룹핑 위해 static method 가진 클래스 사용 가능. Python 에선 모듈 자체가 네임스페이스. my_module.py 에 관련 함수 그룹핑, caller 가 from my_module import f, g. 클래스 불필요. Python stdlib 의 os, math, json 모듈이 정확히 이거.
클래스가 *맞는* 답일 때
공유 state 에 작동하는 메서드 여러 개 가진 stateful 객체. 다형성 원할 때 (같은 인터페이스 여러 구현). 시간 동안 identity 가진 거 모델링 (연결, 세션, stateful 처리기). 클래스가 여기 맞는 도구 — 근데 각 조건이 진짜, 가정 X.
원칙: 함수로 시작. 함수가 지속 state, state 공유 메서드 여러 개, 또는 다형 동작 발달할 때만 클래스로 승격. 클래스에서 함수로 강등이 반대보다 어려움 — 단순하게 시작 + 단순한 형태가 진짜 안 맞을 때만 자라.
Code
함수여야 할 클래스·python
# UNPYTHONIC — __init__ 와 메서드 하나만 가진 클래스
class EmailValidator:
def __init__(self, email):
self.email = email
def is_valid(self):
return "@" in self.email and "." in self.email.split("@")[1]
result = EmailValidator("alice@example.com").is_valid()
# PYTHONIC — 함수
def is_valid_email(email):
return "@" in email and "." in email.split("@")[1]
result = is_valid_email("alice@example.com")
# 같은 로직, 단순한 호출 사이트, 테스트 쉬움, 재사용 쉬움
모듈을 네임스페이스로 — 클래스 불필요·python
# UNPYTHONIC — 헬퍼 그룹핑 위해 static 메서드만 가진 클래스
class StringHelpers:
@staticmethod
def slugify(s):
return s.lower().replace(" ", "-")
@staticmethod
def truncate(s, n):
return s if len(s) <= n else s[:n-3] + "..."
from my_helpers import StringHelpers
result = StringHelpers.slugify("Hello World")
# PYTHONIC — 모듈 레벨 함수
# string_helpers.py
def slugify(s):
return s.lower().replace(" ", "-")
def truncate(s, n):
return s if len(s) <= n else s[:n-3] + "..."
from string_helpers import slugify, truncate
result = slugify("Hello World")
클래스가 값어치 할 때 — 진짜 state·python
# state 공유 메서드 여러 개 가진 stateful 객체 — 클래스가 맞음
class Counter:
def __init__(self):
self.count = 0
self.history = []
def increment(self):
self.count += 1
self.history.append(("increment", self.count))
def reset(self):
self.history.append(("reset", self.count))
self.count = 0
def report(self):
return f"count={self.count}, history={len(self.history)} ops"
# 시간 동안 변하는 두 속성 공유하는 세 메서드.
# 함수면 어색 — Counter 가 맞는 모양.
Closure — 가끔 가벼운 대안·python
# state 필요한데 메서드 여러 개 X? Closure 작동
def make_counter(start=0):
count = [start] # closure 의 변경 위해 list
def increment():
count[0] += 1
return count[0]
return increment
c = make_counter()
print(c()) # 1
print(c()) # 2
print(c()) # 3
# 또는 nonlocal 로
def make_counter_v2(start=0):
count = start
def increment():
nonlocal count
count += 1
return count
return increment
URLBuilder 클래스 — __init__(self, base) 가 base 저장 + 메서드 build(path: str) -> str 이 f"{base}/{path}" 반환. 함수로 변환. 클래스 형태가 맞는 선택일 때 (있다면) 논의. 그 다음 이 클래스를 다른 극단으로 — 클래스 형태가 명확히 맞을 때까지 state + 메서드 여러 개로 확장.
Progress
Progress is local-only — sign in to sync across devices.