클린 코드의 중요성
우리가 코드를 개발하는 이유는 무엇일까? 학교에서 코드를 작성하는 목적은 컴퓨터에 명령을 하기 위해서라고 배웠었다. 하지만 나는 최근 개발공부를 하며 컴퓨터에게 더욱 잘 명령을 내리기 위한 공부를 한다기보다는 다른 개발자분들이 나의 코드를 잘 이해할 수 있도록 짜기위해 노력한다. 나는 다른 개발자분들이 잘 이해할 수 있는 코드를 클린코드라고 생각한다. 클린한 코드를 개발하면 다른 개발자분이 나의 코드를 유지보수하는데 코드를 이해하는 시간을 줄일 수 있어 기술부채를 최소화할 수 있다.
PEP-8이란?
Java도 변수명, 클래스명에 대한 명명규칙과 같은 표준 코딩스타일이 있다. 그와 같이 파이썬도 PEP-8이라는 표준 코딩스타일을 가지고 있다. 이는 이미 파이썬 구문의 많은 특수성을 고려하여 작성되어있으며, 파이썬 구문을 실제로 만든 핵심 파이썬 개발자가 만든 표준이기 때문에 이를 지켜 코드를 구현해주는게 좋다. 이러한 포맷을 활용하여 코드를 작성하면 코드가 일정한 포맷을 가지기 때문에 타 개발자들이 쉽게 읽을 수 있다. 그리고 코드가 주고화되어 한눈에 코드를 읽을 수 있고, 오류를 쉽게 해결하여 코드 품질이 향상될 수 있다. 비록 PEP-8을 사용하여 코드를 작성하였다고 클린코드가 되지는 않지만 그래도 정해진 포맷을 활용해 코드를 구현하는 것이 클린코드를 구현하는 시작이 될 것이다.
(참고: 파이썬을 배우려는 사람들은 웹북을 활용하여 공부하는 것을 추천한다.)
PEP-8 알아보기
이제부터 PEP-8 메뉴얼을 살펴보며 정리하도록 하겠다.
1. 들여쓰기
들여쓰기 - 기본
- 들여쓰기는 스페이스 4번을 표준으로 한다.
- 괄호안 인자들이 줄바꿈이 일어나면 수직정렬 되어야 한다.
# 좋은 예 : 인자가 줄바꿈이 일어나므로 수직 정렬
foo = long_function_name(var_one, var_two,
var_three, var_four)
# 좋은 예 : 인자와 구분을 위해 들여쓰기 2회
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# 좋은 예 : 아래와 같은 형태이면 들여쓰기 1회
foo = long_function_name(
var_one, var_two,
var_three, var_four)
# 나쁜 예 : 수직정렬을 안한 경우
foo = long_function_name(var_one, var_two,
var_three, var_four)
# 나쁜 예 : 들여쓰기가 동일하여 구분 안됨
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
들여쓰기 - if문
if구문에서의 들여쓰기는 선택사항이다. 수직정렬을 해도되고, 아래 if문과 구분을 짓기 위해 들여쓰기를 해도된다.
# if문 들여쓰기를 하지 않은 경우
if (this_is_one_thing and
that_is_another_thing):
do_something()
# if문 들여쓰기를 한 경우
if (this_is_one_thing
and that_is_another_thing):
do_something()
들여쓰기 - 괄호
괄호를 사용할 때 닫는 괄호는 요소와 맞추거나 라인의 시작점과 맞추면 된다.
# 닫는 괄호를 요소에 정렬한 경우
my_list = [
1, 2, 3,
4, 5, 6,
]
# 닫는 괄호를 줄에 맞춘 경우
my_list = [
1, 2, 3,
4, 5, 6,
]
들여쓰기 - Tab, Space
스페이스를 사용하는 것을 권장하지만, 기존 코드가 Tab을 사용한다면 Tab을 사용해도 된다.
하지만 Tab과 Space는 절대로 혼용해서 사용하면 안된다.
2. 줄 바꿈
- 한 줄의 최대 길이는 79자 이내로 제한하는 것이 좋다.
- 닥 스트링과 주석은 72자 이내로 작성해야한다.
- 특정 팀에서 한줄의 길이를 길게 하는 것을 선호한다면 80~100 사이로 늘려도 좋다.
줄 바꿈 - 백 슬레시 활용
with와 같은 구문을 사용할 때 한 줄의 길이가 매우 길어진다면 백슬레시(\)를 활용하여 줄을 바꾸면 된다.
with open('/path/to/some/file/you/want/to/read') as file_1, \
open('/path/to/some/file/being/written', 'w') as file_2:
file_2.write(file_1.read())
줄 바꿈 - 이항 연산자
이항 연산자를 길게 늘여 사용하는 경우 이항 연산자를 앞으로 하여 줄 바꿈을 해주면 된다.
# 좋은 예
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
# 나쁜 예
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
3. 빈 줄
빈 줄은 클래스와 함수의 정의를 구분짓기 위해 사용하기도 하고, 코드에서 연관성 있는 것들을 구분짓기 위해 사용하기도 한다.
- 함수와 클래스의 구분은 2개의 빈줄을 사용한다.
- 클래스 내부 메소드는 1줄의 줄바꿈으로 구분한다.
- 그 외 논리를 구분짓기 위해 줄바꿈을 사용할 수 있다.
def plus(a,b):
return a + b
class hello:
def _hello:
("hello")
def _world:
print("world")
4. import
- import는 한줄에 1개의 모듈을 해주는 것이 바람직하다.
- WildCard(*)을 활용한 import 방식은 지양해야한다.
- 상대경로를 활용한 import는 지양해야함.(단 패키지가 복잡하거나 절대경로가 필요없을 경우 사용 가능)
- import는 특정 그룹으로 그룹화 하여 작성하여준다.(그룹이 다르면 줄바꿈으로 구분해준다.)
- 그룹 1 : 표준 라이브러리
- 그룹 2 : 3rd party 라이브러리
- 그룹 3 : 로컬 라이브러리
import - 나쁜 예
import sys, os
import - 좋은 예
import os
import sys
from subprocess import Popen, PIPE
5. Dunders Names
- Dunders Name은 언더스코어를 두개 앞 뒤로 붙인 이름을 말한다. (__all__, __author__, __version__ 등)
- 항상 닥스트링 뒤 맨 앞에 쓰여진다.(from __future__ import는 예외)
"""This is the example module.
This module does stuff.
"""
from __future__ import barry_as_FLUFL
__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'
import os
import sys
6. String Quoto(따옴표)
- Pythond에서는 "와 '이 구분이 없다.
- 둘 중 어느것을 사용해도 상관이 없다.
- 그러나 닥스트링을 쓸 때는 """을 활용해야한다.
7. 표현식과 구문에서의 공백
- 표현식과 구문에서 불 필요한 괄호는 필요하지 않다.
- 특별한 경우로 index를 나누는 :는 띄어쓰기를 하지 않지만 function annotation에서는 띄어쓰기를 한다.
- index를 나누는 :에서 연산이 들어간다면 띄어쓰기를 해주는 것이 좋다.
- 키워드 독립변수나 default value를 지정할 때 띄어쓰기를 하지마라.
- 이진 연산의 앞뒤에 공백을 붙이되 우선순위가 낮은 것만 붙여라.
# 좋은 예
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower+offset : upper+offset]
def munge(input: AnyStr): ...
def munge() -> AnyStr: ...
def complex(real, imag=0.0): ...
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
# 나쁜 예
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower + offset:upper + offset]
def munge(input:AnyStr): ...
def munge()->PosInt: ...
def complex(real, imag = 0.0): ...
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)
- 추가로 튜플을 선언할 때 뒤에 ,만 붙여 선언할 수 있는데 되도록 괄호를 붙여주도록 하자.
#좋은 예
a = (1,)
#나쁜 예
a = 1,
8. Documentation string
- 독스트링의 마지막 """는 혼자 쓰여야한다.
- 하지만 독 스트링이 한줄이라면 함께 써야한다.
# 독 스트링이 여러줄
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
# 독 스트링이 한줄
"""Return a foobang"""
9. 명명규칙
피해야하는 이름
- I(소문자 엘)
- O(대문자 오)
- I(대문자 아이)
한 글자 변수이름으로 위 3가지를 사용하면 안된다. (몇몇 폰트에서 1,0과 헷갈림)
패키지, 모듈 이름
- 짧게 작성한다.
- 모두 소문자인 이름으로 작성한다.
- 언더스코어는 가독성이 올라갈 수 있을 경우에 모듈에서만 사용한다.
- 패키지에는 언더스코어를 사용할 수 없다.
클래스, 예외 명
- CapWords 작성규칙을 사용한다.(자바의 클래스와 동일)
함수 및 변수 이름
- 함수 이름과 변수 이름은 언더스코어로 구분된 소문자로 구성된다.
상수
- 상수는 대문자와 언더스코어로 구분하여 작성해줍니다.
10. 프로그래밍 권장사항
- not ~ is ~ 보다는 is not을 활용하는 것이 좋다.
# 좋은 예
if foo is not None:
# 나쁜 예
if not foo is None:
- lambda 표현식 대신 def를 사용해라.
# 좋은 예
def f(x): return 2*x
# 나쁜 예
f = lambda x: 2*x
- Object를 비교할 때 isinstance()를 사용해라.
# 좋은 예:
if isinstance(obj, int):
# 나쁜 예:
if type(obj) is type(1):
- 문자열, 리스트, 튜플 등이 비어있는지 체크하려면 if에 직접 넣어 확인해라.
# 좋은 예:
if not seq:
if seq:
# 나쁜 예:
if len(seq):
if not len(seq):
if문에서 문자열, 리스트이 조건으로 된다면 비어있을 경우 false가 된다.
마무리
파이썬 공부를 시작한건 여러모로 나에게 큰 도전이라고 생각한다. 컴퓨터공학을 전공하며 여러가지 언어를 겉핧기식으로만 공부를 했었고 명명규칙을 어느정도 지키면서 작성할 수 있는 언어가 자바밖에 없다는게 너무 부끄러웠다. 백앤드 개발에서 머신러닝으로 진로를 변경하게 되며 이번 2주간 보람차게 파이썬을 열심히 공부하였다. 그런데 파이썬의 기초를 공부하다보니 글또에 제출하기에는 너무 퀄리티 낮은 소재만 나오게되어 많이 고민하게 되었다. 3일간 웹북을 정독하며 모르고 사용한 파이썬을 알게되어 매우 기쁘다. 이제부터는 머신러닝 입문서와 학부때 공부한 인공지능, 데이터과학 수업 PDF를 리마인드하며 다음 글은 좀 더 퀄리티 있는 글이 나올 수 있도록 노력하겠다.
'Language > Python' 카테고리의 다른 글
seaborn을 활용한 시각화 (2) | 2022.09.10 |
---|---|
matplotlib을 활용한 시각화 기초 (0) | 2022.08.29 |