파이썬이라는 프로그래밍 언어를 배우며 느낀점이 있다.
바로 파이썬은 가독성이 뛰어나다는 것이다.
실제로 코드는 무언가를 구현하고 작동시키기 위해 읽혀져야한다.
때문에 우리가 생각 했던 것 이상으로 코드는 자주 읽힌다는 사실을 부정 할수 없다.
때문에 가독성 있게 코드를 짜는 것은 매우 중요하다고 볼 수 있다.
그럼 어떻게 하며 코드를 직관적이고 잘 읽히게 짤 수 있을까?
고민하던 중 아래의 제목을 가진 책을 찾을 수 있었다.
The Hitchhiker's Guide to Python: Best Practices for Development
이 책에서는 General Concept 수준에서 어떤 파이썬 코드가 좋은 코드인지 알려주고있다.
아래는 책의 내용중 'code style' 에 대한 부분을 정리한 것이다.
- 명시적 코드
-파이썬은 가장 솔직한 태도로 작성해야한다.
Bad
def make_complex(*args):
x, y = args
return dict(**locals())
Good
def make_complex(x, y):
return {'x': x, 'y': y}
위 아래 코드를 비교해보면 아래의 좋은 코드는 x와 y가 명시적으로 인자값으로 나왔으며, 명시적으로 사전형태로 반환된다. 이렇게 사용자가 코드를 읽음으로써 무엇을 해야할 정확히 알 수 있는 예가 좋은 예이다.
- 한 줄에 한 문장씩
-list comprehension과 같은 일부 복합적인 문장은 간결함과 표현성이 우수하여 일부 허용되고 인정되지만, 동일한 코드라인에 두 개의 구분되지 않은 진술이 있는 것은 잘못된 관행이다.
Bad
print('one'); print('two')
if x == 1: print('one')
if <complex comparison> and <other complex comparison>:
# do something
Good
print('one')
print('two')
if x == 1:
print('one')
cond1 = <complex comparison>
cond2 = <other complex comparison>
if cond1 and cond2:
# do something
- 반환 값
- 함수의 복잡성이 커질때 return 문을 함수문에 여러번 사용하는 것은 일반적이지 않다. 하지만 함수의 clear intent(명확한 의도)와 sustainable readability level(가독성 수준을 유지하는)을 지속하기 위해서는 함수의 많은 출력지점에서 의미있는 값을 반환하지 않는 것이 바람직하다. (함수의 많은 부분에서 제대로 작동하는지 간단한 장치를 여러개 설치하는것 이라고 생각하면 될 것같다.)
함수에서 값을 반환하는 주요 사례는 두 가지가 있는데, 하나는 함수가 제대로 실행되어 그 결과값이 정상적으로 처리되었을때와 다른 하나는 parameter 또는 다른 이유로 함수가 완벽하게 작동하지 않는다는 뜻을 나타내는 error cases들이 나올때이다.
error cases들이 예외를 일으키는 것을 원하지 않으면 None or False 등을 반환하여 함수가 올바르게 수행되지 않음을 표시한다. 잘못된 맥락을 빠르게 감지한 만큼 함수의 구조를 매끄럽게 하는데 도움이 될 수 있다.
하지만 함수작동의 일반적인 코스에서 여러개의 출구점을 갖는 경우 반환된 값에 대한 디버깅이 어려워 질 수 있기 때문에 하나의 exit point를 유지하는 것이 바람직하다.
def complex_function(a, b, c):
if not a:
return None # Raising an exception might be better
if not b:
return None # Raising an exception might be better
# Some complex code trying to compute x from a, b and c
# Resist temptation to return x if succeeded
if not x:
# Some Plan-B computation of x
return x # One single exit point for the returned value x will help
# when maintaining the code.
- unpacking
-목록 또는 튜플의 길이를 알고 있는 경우 압축을 풀면서 이름을 해당 요소에 할당할 수 있다.
words = 'yesterday all my troubles seemed so far away'.split()
word_lists = []
for i in words:
word_list = [i.upper(),i.lower(), len(i)]
word_lists.append(word_list)
print(word_lists)
a = [[i.upper(),i.lower(), len(i)] for i in words]
print(a)
for i, j in enumerate(words):
print(f'index = {i}, value = {j}')
print(words)
print(list(enumerate(words)))
###############################################################################################
[['YESTERDAY', 'yesterday', 9], ['ALL', 'all', 3], ['MY', 'my', 2], ['TROUBLES', 'troubles', 8], ['SEEMED', 'seemed', 6], ['SO', 'so', 2], ['FAR', 'far', 3], ['AWAY', 'away', 4]]
[['YESTERDAY', 'yesterday', 9], ['ALL', 'all', 3], ['MY', 'my', 2], ['TROUBLES', 'troubles', 8], ['SEEMED', 'seemed', 6], ['SO', 'so', 2], ['FAR', 'far', 3], ['AWAY', 'away', 4]]
index = 0, value = yesterday
index = 1, value = all
index = 2, value = my
index = 3, value = troubles
index = 4, value = seemed
index = 5, value = so
index = 6, value = far
index = 7, value = away
['yesterday', 'all', 'my', 'troubles', 'seemed', 'so', 'far', 'away']
[(0, 'yesterday'), (1, 'all'), (2, 'my'), (3, 'troubles'), (4, 'seemed'), (5, 'so'), (6, 'far'), (7, 'away')]
- 목록 필터링
Bad
반복하는 동안 리스트에서 항목을 제거하지 않기
(Never remove items from a list while you are iterating through it.)
# Filter elements greater than 4
a = [3, 4, 5]
for i in a:
if i > 4:
a.remove(i)
리스트를 여러번 통과하게 만들지 않기 (Don’t make multiple passes through the list.)
while i in a:
a.remove(i)
Good
list comprehension을 쓰거나 generator expression을 사용하자
# comprehensions create a new list object
filtered_values = [value for value in sequence if value != x]
# generators don't create another list
filtered_values = (value for value in sequence if value != x)
출처:https://docs.python-guide.org/writing/style/
아직 파이썬에 대한 이해가 많이 부족해서 완벽하게 이해하지 못한것 같다. 생각날때마다 보면서 이해하려고 노력해야겠다.😢
댓글