이 항목의 핵심 메시지는 "코드는 간결함보다 명료함이 우선"이라는 것입니다. 한 줄로 복잡한 로직을 표현하려는 시도는 종종 가독성을 해치고, 잠재적인 버그를 만들어내기 쉽습니다. 이럴 때 잘 명명된 도우미 함수(Helper Function)를 사용하는 것이 훨씬 효과적인 방법입니다.
먼저, 코드가 어떤 문제를 해결하려 하는지 이해해야 합니다.
urllib.parse.parse_qs
함수는 URL의 쿼리 문자열(예: ?name=value&...
)을 파싱하여 딕셔너리로 만들어 줍니다.
from urllib.parse import parse_qs
my_values = parse_qs('빨강=5&파랑=0&초록=',
keep_blank_values=True)
print(repr(my_values))
# 출력 결과: {'빨강': ['5'], '파랑': ['0'], '초록': ['']}
여기서 중요한 점은 parse_qs
의 결과입니다.
'5'
가 아닌 ['5']
)초록=
)는 빈 문자열을 담은 리스트(['']
)가 됩니다.투명도
)에 접근하려고 하면 에러가 발생하므로 .get()
메서드를 사용해야 합니다.우리가 하려는 작업은 이 딕셔너리에서 각 색상 값을 정수(integer)형으로 안전하게 가져오는 것입니다.
이 문제를 해결하기 위해 다음과 같은 복잡한 한 줄 코드를 사용할 수 있습니다.
# 'or' 트릭을 이용한 복잡한 식
red = my_values.get('빨강', [''])[0] or 0
green = my_values.get('파랑', [''])[0] or 0 # 의도와 다른 키('파랑')를 사용하는 실수
opacity = my_values.get('투명도', [''])[0] or 0
print(f'빨강: {red!r}') # 출력: '5' (문자열)
print(f'초록: {green!r}') # 출력: '0' (문자열)
print(f'투명도: {opacity!r}') # 출력: 0 (정수)
이 코드의 문제점:
.get()
의 기본값, 리스트 인덱싱(''), 그리고 or
연산자의 단락 평가(short-circuit) 원리까지 한 번에 이해해야 합니다. 코드를 처음 보는 사람은 의도를 파악하기 어렵습니다.red
의 값은 문자열 '5'
이지만, opacity
의 값은 정수 0
입니다. 이렇게 반환 타입이 일관되지 않으면 나중에 타입 관련 버그(TypeError)를 유발할 수 있습니다.green
변수에 파랑
키를 사용하는 실수가 발생했습니다. 코드가 명료했다면 이런 실수를 더 쉽게 발견했을 것입니다.위 문제를 해결하기 위해 코드를 조금 더 풀어쓰면 가독성이 약간 향상됩니다.
# if/else 조건부 표현식 사용
red_str = my_values.get('빨강', [''])
red = int(red_str[0]) if red_str[0] else 0
이 코드는 or
트릭보다는 의도가 명확합니다. "문자열이 존재하면 정수로 바꾸고, 그렇지 않으면 0으로 설정하라"는 의미를 더 쉽게 읽을 수 있습니다.
하지만 여전히 문제입니다. 만약 파라미터를 10개 처리해야 한다면, 이 두 줄짜리 로직을 10번 반복해야 합니다. 이는 코드 중복을 야기하며, 나중에 로직을 수정해야 할 때 10곳을 모두 고쳐야 하는 유지보수의 어려움을 만듭니다.
이 모든 문제를 해결하는 가장 좋은 방법은 로직을 도우미 함수로 분리하는 것입니다.
def get_first_int(values, key, default=0):
found = values.get(key, [''])
if found[0]:
# 값이 존재하면 정수로 변환하여 반환
return int(found[0])
# 키가 없거나 값이 비어있으면 기본값 반환
return default
# 도우미 함수 사용
green = get_first_int(my_values, '초록')
red = get_first_int(my_values, '빨강')
opacity = get_first_int(my_values, '투명도')
print(f'초록: {green}') # 출력: 0
print(f'빨강: {red}') # 출력: 5
print(f'투명도: {opacity}') # 출력: 0
도우미 함수의 장점:
get_first_int(my_values, '초록')
이라는 코드만 봐도 "my_values에서 '초록' 키에 해당하는 첫 번째 값을 정수로 가져온다"는 의도가 명확하게 드러납니다.try-except ValueError
)를 추가하고 싶다면, 함수 내부만 한 번 수정하면 이 함수를 사용하는 모든 곳에 적용됩니다.복잡한 로직을 한 줄의 표현식으로 압축하려는 유혹을 피해야 합니다.
대신, 로직의 의도를 명확히 설명하는 이름의 도우미 함수를 작성하세요.
이렇게 하면 코드가 더 명료해지고, 재사용하기 쉬워지며, 미래에 수정하기도 훨씬 수월해집니다. 이는 파이썬다운 코드를 작성하는 중요한 원칙 중 하나입니다.