코딩 스타일
목차
참고 시 좋은 자료
- 파이썬의 PEP 8
- 구글의 파이썬 스타일 가이드
- 『Clean Code 클린 코드』(로버트C 마틴 지음, 박재호 외 옮김)
- 하지만 자바기준으로 작성했다는 한계 존재
- 『프로그래밍 수련 법』(브라이언W.커니핸,롭 파이크 지음. 김정민 옮김)
- 오래되었다는 단점
- C관점으로 보려면 추가 업데이트 필요
변수명과 주석
[EX] 문자열에 매칭된 서브 시퀀스의 개수를 구하는 코드.
- [풀이 1]
- 코드 내에 변수명을 아무렇게나 지정하고 주석도 없이 작성한 코드부터 살펴보자.
def numMatchingSubseq(self, S: str, words: List[str]) -> int:
a = 0
for b in words:
c = 0
for i in range(len(b)):
d = S[c:].find(b[i])
if d < 0:
a -= 1
break
else:
c += d + 1
a += 1
return a
(단점) 변수명이 무엇을 의미하 는지를 이해하기가 어려움
알고리즘에 대한 주석이 없어서 어떻게 동작하는지 파악하 기도 쉽지 않음.
주석을 상세히 달 필요 있음
[풀이 2]
def numMatchingSubseq(self, S: str, words: List[str]) -> int:
matched_count = 0
for word in words:
pos = 0
for i in range(len(word)):
# Find matching position for each character.
found_pos = S[pos:].find(word[i])
if found_pos < 0:
matched_count -= 1
break
else: # If found, take step position forward.
pos += found_pos + 1
matched_count += 1
return matched_count
간단한 주석과 알 수 있는 변수이름 부여하는게 좋음
주석은 한글로 달아도 무방하지만 영어로 작성하는 것에도 부담이 없어야 한다.
최소한 자연스럽게 영어로 주석을 읽고 쓰는 데 아무런 부담이 없을 정도로 익숙해져야 한다.
온라인 코딩 테스트 시에도 영어로 주석을 달아서 제출하는 편이 좀 더 프로페셔널하다는 인상을 줄 수 있다.
리스트 컴프리헨션 주의점
- 파이썬의 매우 강력한 기능 중 하나며, 파이썬을 대표하는 특징 중 하나다.
- 단점: 특유의 문법과 의미를 축약하여 나타내는 특징 탓에 지나치게 남발하게 되면 파이썬의 가독성을 떨어트림
(가독성을 떨어트리는 대표적인 경우)
str1s = [str1[i:i + 2].lower() for i in range(len(str1) - 1) if re.findall('[a-z] {2}', str1[i:i + 2].lower())]
리스트 컴프리헨션은 그 강력함으로 인해 대부분 한 줄로 적게 되는 경우가 많은데,
이경우에도 가능한 대로 다음과 같이 역할별로 줄 구분을 하면 훨씬 더 가독성이 높아지고 이해하기 쉬워진다.
(줄 바꿈으로 코드 정리)
str1s = [
str1[i:i + 2].lower() for i in range(len(str1) - 1)
if re.findall('[a-z]{2}', str1[i:i + 2].lower())
]
리스트 컴프리헨션은 여전히 풀어쓰는 것에 비해서는 가독 성이 떨어짐
(풀어씀)
str1s = []
for i in range(len(str1) - 1):
if re.findall('[a-z]{2}', str1[i:i + 2].lower()):
str1s.append(str1[i:i + 2].lower())
차라리 이처럼 모두 풀어서 쓰는 것도 가독성을 위해서라면 나쁘지 않음.
이해하기가 쉽다.
굳이 짧은줄 수를 고집할 필요는 없다.
경우에 따라서는 가독성을 위해 모두 풀어쓰는 것도 검토해볼 만하다.
리스트 컴프리헨션은 대체로 표현식이 2개를 넘지 않아야 한다.
(여러줄에 걸쳐 리스트 컴프리헨션을 써 가독성을 떨어뜨린 경우)
return [(x, y, z)
for x in range(5)
for y in range(5)
if x != y
for z in range(5)
if y != z]
구글 파이썬 스타일 가이드
: 가독성을 높이기 위한 지침 들이 많은데, 이 절에서 소개하는 ‘코딩 스타일’과도 잘 부합하는 주제이므로 구글 파이썬 스타일 가이드의 여러 지침 중 몇 가지만 살펴보자.
1. 함수의 기본 값으로 가변 객체 Mutable Object를 사용하지 않아야 함.
- 함수가 객체를 수정하면(리스트에 아이템을 추가한다든지 등) 기본값이 변경되기 때문.
- 따라서 다음과 같이 기본값으로 [] 나 {} 를 사용하는 것은 지양해야 한다.
- 대신 불변 객체 Immutable Object 를 사용 None 을 명시적으로 할당하는 것도 좋은 방법
(기본값으로 [] 나 {} 를 사용한 좋지 않은 예)
No: def foo(a, b=[]):
...
No: def foo(a, b: Mapping = {}):
...
(Immutable Object, None 을 명시적으로 할당한 좋은 예)
Yes: def foo(a, b=None):
if b is None:
b = []
Yes: def foo(a, b: Optional[Sequence] = None):
if b is None:
b = []
2. True , False 를 판별할 때는 암시적(Implicit)인 방법을 사용하는 편이 간결하고 가독성이 높다.
- 즉 굳이 False 임을 if foo != []: 같은 형태로 판별할 필요가 없다.
- if foo: 로 충분
이외에도 몇 가지 더 정리해보면
Yes:
if not users:
➊ print('no users')
if foo == 0:
➋ self.handle_zero()
if i % 10 == 0:
➌ self.handle_multiple_of_ten()
No:
if len(users) == 0:
print('no users')
if foo is not None and not foo:
self.handle_zero()
if not i % 10:
self.handle_multiple_of_ten()
[설명]
len(users) == 0 으로 길이가 없다는 말은 값이 없다는 뜻
➊ 과 같이 not users 로충분
len(users) == 0 으로 길이가 없다는 말은 값이 없다는 뜻
➋ 정수를 처리할 때는 (2)와 같이 비교 대상이 되는 정수값을 직접 비교하는 편이 덜 위험
암시적으로 거짓 여부를 판별는 것은 좋지 않음
➌ 모듈로 연산 결과가 0인 것을 과 같이 i % 10 == 0 로 명시적으로 Explicitly 값을 비교하는 편이 좋음.
정수로 처리하지 않고 암시적 거짓 여부로 판별하는 것은 위험.
뿐만 아니라 가독성도 떨어짐
3. 최대 줄 길이는 80자로 한다.
- 이제 대부분 큰 모니터를 사용하지만 여전히 줄의 가로 길이는 길어서는 안 된다는 암묵적인 약속이 있다.
- 구글 스타일 가이드에서도 마찬가지로 80자로 제한하고 있다.
파이썬다운 방식(Pythonic Way)
: 파이썬에서는 언어 차원에서 Zen of Python이라는 이름으로 이러한 철학을 제공.
- import this 명령으로 실행 가능
>>> import this
The Zen of Python, by Tim Peters
아름다움이 추함보다 낫다
명시적인 것이 암시적인 것보다 낫다
단순함이 복잡함보다 낫다
복잡함이 꼬인 것보다 낫다
수평이 계층보다 낫다
여유로운 것이 밀집된 것보다 낫다
가독성이 중요하다
특별한 경우라는 것은 규칙을 어겨야 할 정도로 특별한 것이 아니다
비록 실용성이 순수성에 우선하지만 에러 앞에서는 절대 침묵하지 말라
명시적으로 에러를 감추려는게 아니라면.
모호함을 앞에 두고 이를 유추하겠다는 유혹을 버려라
문제를 풀어낼 -바람직 하고도 유일하며- 명확한 방법이 존재할 것이다
…
파이썬을 사용하면서 항상 되새겨야 할 내용.