본문 바로가기
Python Basic

파이썬의 코딩 컨벤션과 PEP8 가이드

by mjk0618 2023. 9. 27.

개발자에게 강조되는 역량 중 하나는 협업입니다. 프로젝트를 진행할 때 일반적으로 여러 인원이 각자의 역할을 부여받고 각 프로그램의 컴포넌트를 독립적으로(또는 함께) 개발하게 됩니다. 결국은 팀원들이 각자 구현한 코드를 모아서 검토하고 합치는 과정이 필요한데, 사람마다 코드를 짜는 스타일이 다르면 이 과정에서 여러 문제를 겪게 됩니다. 이런 문제를 방지하기 위한 다양한 방법이 있는데 그 중에서 코딩 컨벤션에 대해서 정리해보았습니다.

 

코딩 컨벤션이란?

코딩 컨벤션(coding conventions)는 특정한 프로그래밍 언어를 사용할 때 일반적으로 권고되는 코드 스타일에 대한 가이드라인을 의미합니다. 컨벤션은 파일 구조, 여백, 주석, 선언문, 공백, 명명 규칙 등을 포함합니다. 가독성과 유지보수를 위해서 가급적 가이드를 따르는 것이 권장됩니다. 일반적으로 코딩 컨벤션이라고 하면 같은 프로젝트를 진행하는 팀원들간의 지켜지는 규칙을 의미하는데, 이 글에서는 파이썬의 PEP8에 대해서 설명하겠습니다. 코딩 컨벤션 개념에 대한 구체적인 내용은 위키피디아 문서를 참고해주세요.

 

PEP8이 필요한 이유

PEP8은 좋은 파이썬 코드를 작성하기 위해서 제공되는 가이드라인입니다. 2001년 파이썬의 창시자 귀도 반 로섬(Guido van Rossum)등에 의해 작성되었습니다. PEP8은 코드의 가독성을 향상하고 일관성을 유지하는데 중점을 둡니다.

 

PEP은 Python Enhancement Proposal을 의미하는데, 직역하면 파이썬 개선 제안을 의미합니다. PEP은 파이썬에서 제안된 새로운 기능을 설명하고 커뮤니티를 위해 디자인 및 스타일 등을 문서화한 것입니다.

 

Readbility counts.
- The Zen of Python

 

The Zen of Python을 통해 파이썬의 철학을 엿볼 수 있는데, 그 중 위와 같은 문구가 있습니다. 가독성을 매우 중요시한다는 것을 알 수 있습니다. 참고로 전문은 import this 를 실행하면 볼 수 있습니다. 마치 하나의 이스터에그 같네요.

 

귀도 반 로섬은 “코드는 쓰이는 것보다 더 많이 읽힌다.”라고 하였습니다. 당신은 유저 승인을 위한 코드를 몇 분 만에, 혹은 한나절을 걸려서 쓸 수도 있습니다. 일단 한번 다 쓰고 나면 같은 코드를 다시 쓸 일은 없을 것입니다. 하지만 다시 읽을 일은 분명히 있습니다. 그 코드는 프로젝트의 일부가 될 테고, 다시 그 파일을 찾아갈 때마다, 코드가 왜 그렇게 쓰였는지 기억해야 할 것입니다. 결국, 가독성이 중요합니다. 이제 지루한 이야기는 이쯤에서 마치고 PEP8에서 제안하는 몇가지 주요한 코드 스타일 가이드를 소개하겠습니다.

 

참고로 본 글의 내용은 파이썬 튜토리얼 사이트인 RealPython의 글을 참고하였습니다.

 

명명 규칙

파이썬 코드를 작성하다보면, 변수, 함수, 클래스, 패키지 등 이름을 부여할 일이 정말 많습니다. 이 때 각 type에 대한 일반적인 명명 규칙(naming conventions)이 PEP8에 잘 정리되어 있습니다.

 

타입 명명 규칙 Examples
함수 (function) 소문자 단어를 사용합니다. 각 단어는 밑줄(underscore)로 구분합니다. function, my_function
변수 (variable) 소문자 단어를 사용합니다. 각 단어는 밑줄(underscore)로 구분합니다. x, var, my_variable
클래스 (class) 각 단어의 시작을 대문자로 하고, 밑줄 등 구분자를 사용하지 않습니다. Model, MyClass
메서드 (method) 소문자 단어를 사용합니다. 각 단어는 밑줄(underscore)로 구분합니다. class_method, method
상수 (constant) 모든 글자는 대문자를 사용합니다. 각 단어는 밑줄로 구분합니다. CONSTANT, MY_CONSTANT
모듈 (module) 간결한 단어를 사용하여 소문자로 표기합니다. 각 단어는 밑줄로 구분합니다. module.py, my_module.py
패키지 (package) 간결한 단어를 사용하여 소문자로 표기합니다. 각 단어는 밑줄로 구분합니다. package, mypackage

 

이 규칙은 정말 일반적이고 기본적인 규칙입니다. 참고로 단어를 소문자로 표기하고 밑줄로 구분하는 방식은 snake_case, 모든 단어의 첫 글자를 대문자로 표기하고 구분자를 사용하지 않는 방식을 PascalCase라고 하고, 첫 글자를 제외한 단어의 첫 글자를 대문자로 하는 방식은 camelCase라고 합니다.

 

추가로 몇 가지 명명 규칙을 설명하면 다음과 같습니다.

 

  1. 함수는 코드의 기능을 잘 표현하는 동사를 사용합니다.
  2. 변수와 클래스의 이름에는 동사 사용을 지양합니다.
  3. 변수명에는 관사 사용은 지양하고 필요에 따라 단수 복수 표기는 권장됩니다.
  4. 사용하는 단어가 길 경우 축약합니다.

 

4번은 구체적으로 probability 대신 prob, index 대신 idx등의 예시가 있습니다. 또한 temp, freq, info 등 통상적으로 사용하는 변수명을 사용하는 것이 좋습니다. 의미를 알 수 없는 변수명은 가급적 사용하지 않고, boolean 값을 리턴하는 함수나 상태를 저장하는 변수의 이름은 일반적으로 is로 시작합니다.

 

# 클래스의 이름에는 동사 사용을 지양합니다.
class CollectWebData # (X)
class WebCrawler # (O)

# 관사 사용을 지양하고 단수 복수 표기를 권장합니다.
the_number_of_members = 5 (X)
num_members = 5 (O)

# boolean을 리턴하거나 상태를 저장하는 변수는 is로 시작합니다.
def is_prime_number(num):
    pass

 

코드 구분

원문에선 vertical whitespace 또는 blank lines라고 하며 코드 가독성을 위해서 사용합니다.

최상위(top-level) 함수와 클래스는 두 개의 빈 줄로 구분합니다.

 

class MyFirstClass:
    pass

class MySecondClass:
    pass

def top_level_function():
    return None

 

클래스 내의 메서드는 하나의 줄로 구분합니다.

 

class MyClass:
    def first_method(self):
        return None

    def second_method(self):
        return None

 

함수 내에서 단계를 명확하게 구분할 수 있는 구분선을 사용합니다. 아래 함수는 통계학에서 분산을 계산하는 공식 $Var(X) = E[X^2]-E[X]^2$에 따라 두 단계로 구분하여 코드를 작성하였습니다.

 

def calculate_variance(number_list):
    sum_list = 0
    for number in number_list:
        sum_list = sum_list + number
    mean = sum_list / len(number_list)

    sum_squares = 0
    for number in number_list:
        sum_squares = sum_squares + number**2
    mean_squares = sum_squares / len(number_list)

    return mean_squares - mean**2

 

최대 길이 및 줄바꿈

PEP8은 한 줄의 코드가 79자를 넘어가지 않는 것을 권장합니다. 하지만 이걸 일일히 셀 수는 없고, 적당 한 곳에서 줄바꿈을 수행해야 하는데, 이게 항상 자연스럽게 되지는 않습니다. 다행히 파이썬은 백슬래시를 사용하여 임의로 코드 줄바꿈을 할 수 있습니다.

 

from mypkg import example1, \\
    example2, example3

 

수식이 길어질 경우 연산자를 기준으로 다음과 같은 형태로 줄바꿈합니다. 연산자가 줄의 처음에 오면, 수식이 어떤 역할을 하는지 조금 더 이해하기 쉽기 때문에 이 방식을 사용합니다.

 

# 권장하는 방법
total = (first_variable
         + second_variable
         - third_variable)

# 권장하지 않음
total = (first_variable +
         second_variable -
         third_variable)

 

공백 및 들여쓰기

파이썬의 들여쓰기에는 보통 네 개의 공백을 사용합니다. 연산식에 사용하는 공백에 집중해서 설명해보겠습니다. 이 부분은 항상 사람마다 스타일이 달라서 궁금했던 내용인데, 이번에 권장되는 스타일이 무엇인지에 대해서 조금 더 명확하게 알게 되었습니다.

함수의 디폴트 파라미터(default parameter)에는 공백을 사용하지 않습니다.

 

# 권장하는 방법
def function(default_parameter=5):
    # ...

# 권장하지 않음
def function(default_parameter = 5):
    # ...

 

일반적으로 연산자(operator)와 피연산자(operand) 사이에는 공백이 사용됩니다. 하지만 수식에 다양한 연산이 혼재될 경우 우선 순위가 낮은 연산에는 공백을 사용하지 않습니다.

 

# 권장하는 방법
y = x**2 + 5
z = (x+y) * (x-y)

# 권장하지 않음
y = x ** 2 + 5
z = (x + y) * (x - y)

 

시퀀스 자료형의 슬라이싱 또는 인덱싱에서 콜론은 이진 연산자로 취급됩니다. 따라서 다음과 같은 방식으로 공백을 사용하는 것이 권장됩니다.

 

list[3:4]

# 콜론은 가장 낮은 우선순위의 연산으로 취급됩니다.
list[x+1 : x+2]

# 콜론 앞 뒤로 같은 개수의 공백을 사용합니다.
list[3:4:5]
list[x+1 : x+2 : x+3]

# 콜론 뒤의 값이 생략될 경우 공백도 생략합니다.
list[x+1 : x+2 :]

 

PEP8 가이드를 준수하기 위한 편리한 방법

일부 라이브러리는 코드 스타일을 검토하거나 정해진 컨벤션에 맞게 자동으로 수정해줍니다. 다음과 같이 라이브러리를 설치한 후 사용할 수 있습니다.

 

Linters

린터는 코드를 분석하고 오류를 표시해주는 프로그램입니다. 오류가 발생하면 수정 방법을 제안합니다.

 

# pycodestyle 사용하기
$ pip install pycodestyle
$ pycodestyle code.py

# flake8 사용하기
# flake8은 pycodestyle과 디버깅 도구인 pyflakes를 통합한 라이브러리입니다.
$ pip install flake8
$ flake8 code.py

# 예시 출력
code.py:1:17: E231 missing whitespace after ','
code.py:2:21: E231 missing whitespace after ','
code.py:3:17: E999 SyntaxError: invalid syntax
code.py:6:19: E711 comparison to None should be 'if cond is None:'

 

Autoformatters

black 라이브러리는 PEP 8 스타일에 맞게 코드를 자동으로 리팩토링해줍니다. 다음과 같은 명령어로 설치 후 사용할 수 있습니다.

 

$ pip install black

$ black code.py
reformatted code.py
All done! ✨ 🍰 ✨

 

아래는 black을 적용하기 전과 후의 코드를 비교한 것입니다.

 

# black 적용 전
for i in range(0,3):
    for j in range(0,3):
        if (i==2):
            print(i,j)

# black 적용 후
for i in range(0, 3):
    for j in range(0, 3):
        if i == 2:
            print(i, j)

 

vscode에서는 format-on-save라는 기능을 사용하여 Ctrl + S를 눌러 저장할 때마다 자동으로 black에 의한 포매팅이 수행될 수 있게 하는 기능이 있습니다. Ctrl + Shift + P 명령어로 나타난 검색창에 settings를 검색하고 다음을 클릭합니다.

 

 

settings.json에 접근 후 아래와 같은 코드를 추가하면 터미널 명령어가 아닌 저장을 할 때마다 자동으로 포매팅이 수행되게 할 수 있습니다.

 

댓글