CH1. 파이썬답게 생각하기
파이써닉(Pythonic) 이라는 형용사는 협업하는 과정에서 자연스레 생겨난 스타일이다.
추상적인 것보단 명시적인 것을, 복잡한 것보다는 단순한 것을, 읽기 어려운 것보단 가독성을 최대한 높이려는 노력 — 이 파이썬다운 방식을 따르는 게 좋다.
파이썬의 선(禪 홀로 보일 or 물려줄 선, The Zen of Python) → import this
ITEM 1 : 사용 중인 파이썬의 버전을 알아두라
이 책은 2024년 10월 배포된 Python 3.13 구문을 기준으로 한다.
파이썬 2는 2020년 4월 20일, 버전 2.7.18을 마지막으로 공식 지원이 종료되었고 이후 포팅 작업이 이루어졌다.

ITEM 2 : PEP 8 스타일 가이드를 따르라
PEP(Python Enhancement Proposal) #8 — 파이썬 공식 스타일 가이드
→ https://peps.python.org/pep-0008/ (한 번쯤 읽어볼 것을 권장)
- 들여쓰기는 탭 대신 스페이스 4칸
- 한 줄은 79자 이하
- 함수·클래스 사이는 빈 줄 2개
- 클래스 안 메서드 사이는 빈 줄 1개
- 딕셔너리는
{key: 값}형태로 - 변수 대입 시
변수 = 1처럼 한 줄에 하나씩만 - 타입 힌트는
변수: int = 1형태로 - 함수·어트리뷰트·변수명은
lowercase_underscore - 보호 속성은
_leading_underscore, 비공개는__double_underscore - 클래스명은
CapWords(첫 글자 대문자) if not a is 10대신if a is not 10- 빈 컨테이너 검사는
if len(x) == 0대신if not x - 한 줄짜리
if,for,while,except는 피하라 - 여러 식을 쓸 땐 괄호로 감싸고 여러 줄로 나눠 들여쓰기
import는 항상 파일 맨 앞에, 절대 경로로 작성한다.
순서는 표준 라이브러리 → 서드파티 모듈 → 자체 모듈 순으로 구분하고 알파벳순으로 정렬한다.
위 규칙 전체는 black 또는 pylint 를 사용해 자동화하는 것도 좋다.
ITEM 3 : 파이썬의 컴파일 시점에 오류 발견을 기대하지 말라
def bad_refer():
printf(my_var) # printf는 없는 함수
my_var = 123
def bad_math():
return 1 / 0
동적 언어이기 때문에 위 코드도 정의만 해서는 아무 예외가 발생하지 않는다.
이를 보완하려면 typing 내장 모듈을 활용하거나 pytest로 테스트를 작성해야 한다.
ITEM 4 : 복잡한 식을 쓰는 대신 도우미 함수를 작성하라
from urllib.parse import parse_qs
my_values = parse_qs("적=5&청=0&녹=")
red = my_values.get("적", [""])[0] or 0
green = my_values.get("녹", [""])[0] or 0 # 값이 없으면 0
# 위 방식보다 명확한 삼항 표현
green_str = my_values.get("녹", [""])
green = int(green_str[0]) if green_str[0] else 0 # 그래도 여전히 한눈에 파악하기 어려움
# 도우미 함수로 분리하면 가독성이 훨씬 좋아진다
def get_first_int(v, k):
found = v.get(k, [""])
if found[0]:
return int(found[0])
return 0
print(f"적: {red!r}")
# !r → repr()로 출력 (문자열이면 따옴표까지 포함해서 표시)
코드를 줄여 쓰는 것보다 가독성을 높이는 것이 언제나 더 가치 있다.
DRY(Don't Repeat Yourself) 원칙을 따르라.
ITEM 5 : 인덱스 대신 다중 대입으로 언패킹하라
불변 순서쌍을 만드는 tuple 내장 타입이 있다.
(비슷한 데이터 구조가 필요하지만 진정한 불변이 필요하다면 dataclass를 사용하라.)
파이썬에는 언패킹(unpacking) 구문이 있어 한 문장에서 여러 값을 동시에 대입할 수 있다.
item = ("엿", "식혜")
first, second = item # 언패킹
# 버블 정렬에서의 스왑
def bubble_sort(a):
for _ in range(len(a)):
for i in range(1, len(a)):
if a[i] < a[i - 1]:
a[i - 1], a[i] = a[i], a[i - 1] # 임시 변수 없이 스왑 가능
# enumerate와 함께 쓰면 인덱스와 값을 동시에 꺼낼 수 있다
for idx, value in enumerate(my_list):
...
ITEM 6 : 원소가 하나뿐인 튜플은 항상 괄호로 둘러싸라
one_element = (1) # 정수로 인식
one_element = (1,) # 튜플로 인식 — 트레일링 컴마가 핵심
# 리스트 안에 튜플을 넣을 때도 명확하게
list_c = [(1,)] # 올바른 표현
ITEM 7 : 단순한 인라인 로직에는 조건식 사용을 검토하라
파이썬의 if문은 식(expression)이 아니라 문(statement)이다.
C와 가장 다른 점은 조건이 참일 때 평가되는 식이 맨 앞에 온다는 것이다.
def fail():
raise Exception("이런")
x = fail() if False else 20
print(x) # 20 — False이므로 fail()은 호출되지 않음
# and/or를 이용한 C 스타일 표현 (비추천 — 헷갈림)
x = (i % 2 == 0 and "짝수") or "홀수"
# and는 첫 번째 거짓값, or는 첫 번째 참값을 반환 — 언어마다 동작이 달라 혼란스러울 수 있다
# 바다코끼리 연산자 (:=) 예시
## 기존 방식
s = 'walrus eat kimchi'
result = 'walrus' in s
if result:
print(s)
print(result)
## := 사용
if result := 'walrus' in (s := 'walrus eat kimchi'):
print(s)
print(result)
# 조건문 안에서도 활용 가능
x, y = 2, 1
if x and (z := x > y):
...
ITEM 8 : 대입식(:=)을 사용해 반복을 피하라
대입식(assignment expression)은 바다코끼리 연산자(walrus operator) 라고도 부른다.
# 기존 방식
count = item.get("형준", 0)
if count:
print(count)
# count를 해당 블록에서만 쓴다면 := 으로 간결하게
if count := item.get("형준", 0):
print(count)
# elif와 조합하면 switch문처럼 활용 가능
if (count := item.get("바나나", 0)) >= 6:
...
elif (count := item.get("바나나", 0)) >= 4:
...
elif (count := item.get("바나나", 0)) >= 2:
...
ITEM 9 : 구조 분해가 필요할 때 match를, 단순 분기엔 if문을 써라
match는 Python 3.10에서 도입된 기능으로 러닝 커브가 있는 편이다.
핵심 강점은 구조 분해(destructuring) 가 가능하다는 점이다. 필요해지면 더 깊게 파고들어도 좋다.
def take_action(light):
if light == "빨강":
print("멈춰")
elif light == "초록":
print("가자")
def take_match_action(light):
match light:
case "빨강":
print("멈춰")
case "초록":
print("달려")
case _:
print("알 수 없는 신호")
# enum과 함께 사용하면 타입 안전성도 확보
import enum
class ColorEnum(enum.Enum):
RED = "빨강"
def take_enum_action(light):
match light:
case ColorEnum.RED:
print("멈춰")
# 이진 트리 순회 예시 — match의 진가가 드러나는 케이스
my_tree = (10, (7, None, 9), (13, 11, None))
def contains_match(tree, value):
match tree:
case (pivot, left, _) if value < pivot:
return contains_match(left, value)
case (pivot, _, right) if value > pivot:
return contains_match(right, value)
case (pivot, _, _) | pivot:
return pivot == value
정리
이 챕터는 파이써닉한 파이썬을 쓰기 위한 기본 예열 같은 챕터였다.
- 파이썬답게 짜고
- 동적 바인딩 언어의 특성을 자각하며
- 재사용 가능한 코드를 작성하고
- 언패킹이 강력한 언어 특성임을 활용하며
- 조건식이 다른 언어보다 문장(statement)에 가까운 점을 이해하고
- 바다코끼리 연산자(
:=)도 적극 활용하며 - 필요하다면 C언어의 switch문 같은
match도 있으니 참고하라
는 흐름으로 구성된 챕터였다.
특히 match 키워드는 알아두면 생각보다 요긴하게 쓰일 것 같으니, 기회가 되면 좀 더 깊게 공부해보면 좋을 것 같다.
'스터디 > 책 모임' 카테고리의 다른 글
| [PySpark] 스파크 완벽 가이드 - 5장 구조적 API 기본 연산 (1) | 2024.05.02 |
|---|---|
| [PySpark] 스파크 완벽 가이드 - 4장 구조적 API 개요 (1) | 2024.05.02 |
| [PySpark] 스파크 완벽 가이드 - 17장 스파크 배포 환경 (0) | 2024.04.24 |
| [PySpark] 스파크 완벽 가이드 - 16장 스파크 어플리케이션 개발하기 (0) | 2024.04.24 |
| [PySpark] 스파크 완벽 가이드 - 15장 클러스터에서 스파크 실행하기 (0) | 2024.04.24 |