[Python] 가독성 향상을 위한 스타일 가이드 (PEP8)

 

PEP8은 파이썬 코드를 작성할 때 지켜야 하는 스타일 가이드입니다. 가독성과 일관성을 높이기 위해 권장되며, 코드의 품질을 향상시키기 위한 기준으로 사용됩니다. PEP8의 주요 규칙들은 다음과 같습니다. 

 


1. 들여쓰기 (Indentation)

 

PEP8에서는 코드 블록을 구분하기 위해 4개의 공백 문자를 사용해 들여쓰기를 합니다. 탭 대신 공백 문자를 사용하는 것이 권장됩니다.

 

아래 예시에서 foo() 함수는 권장하는 들여쓰기 방법으로 작성되어 있습니다. if문과 else문의 블록은 각각 4개의 공백으로 들여쓰기되어 있습니다. bar() 함수는 들여쓰기가 일관되지 않아 가독성이 떨어집니다. if 문과 else 문에서 들여쓰기에 사용하는 공백의 개수가 다릅니다. baz() 함수는 탭 문자를 사용하여 들여쓰기가 적용되었습니다.

 

# 적절한 들여쓰기 방법
def foo():
    if x == 1:
        x += 1
    else:
        x -= 1

# 들여쓰기가 일관되지 않은 경우
def bar():
  if x == 1:
   x += 1
  else:
      x -= 1

# 들여쓰기에 탭을 사용한 경우
def baz():
    if x == 1:
        x += 1
    else:
        \tx -= 1

 


2. 최대 줄 길이 (Line length)

 

PEP8에서는 한 줄의 최대 길이를 79자로 제한하고 있습니다. 이는 코드를 읽고 쓰기 쉽게 만들어주는 중요한 규칙 중 하나입니다. 한 줄이 79자를 넘어가면 다음과 같이 처리하라고 권장하고 있습니다

  • 문자열, 주석 등 긴 라인이 필요한 경우에는 여러 줄로 나누어 쓰는 것이 좋습니다.
  • 파이썬에서는 괄호, 중괄호, 대괄호 등으로 둘러싸인 표현식에서는 줄 바꿈을 할 수 있습니다.
  • 줄 바꿈을 할 경우에는 연산자의 앞이나 뒤에서 한 번씩 띄어쓰기를 해주는 것이 좋습니다.
  • 한 줄이 79자를 넘지 않더라도, 가독성을 위해 적절한 위치에서 줄 바꿈을 해주는 것이 좋습니다.

 

아래 예시에서, foo() 함수는 한 줄이 79자 이하로 작성되어 있습니다. bar() 함수에서는 한 줄이 79자를 넘어가기 때문에, 문자열을 여러 줄로 나누어 작성하였습니다. baz() 함수에서는 괄호 안에서 줄 바꿈을 사용하여 한 줄이 너무 길어지는 것을 방지하였습니다. qux() 함수에서는 연산자 앞이나 뒤에서 줄 바꿈을 사용하여, 괄호 안에서 줄 바꿈을 사용하지 않고도 한 줄이 너무 길어지는 것을 방지하였습니다.

 

# 한 줄이 79자 이하인 경우
def foo():
    long_string = "This is a very long string that fits within the 79 character limit."

# 한 줄이 79자를 넘는 경우
def bar():
    long_string = "This is a very long string that exceeds the 79 character limit. " \
                  "To make it more readable, it is split into multiple lines."

# 괄호 안에서의 줄 바꿈
def baz():
    result = (a + b +
              c + d +
              e + f)

# 연산자 앞이나 뒤에서의 줄 바꿈
def qux():
    result = a + b + \
             c + d + \
             e + f

 


3. 공백 (Whitespace)

 

PEP8에서는 코드의 가독성을 높이기 위해 공백(Whitespace)을 적절하게 사용하는 것을 권장하고 있습니다. 

 

  • 들여쓰기에는 항상 공백 4개를 사용합니다.
  • 키워드와 괄호 사이, 콜론과 문장 사이, 연산자와 피연산자 사이에는 항상 공백을 사용합니다.
  • 함수나 메서드의 인자 목록에서 각 인자 사이에는 항상 공백을 사용합니다.
  • 괄호 안쪽이나 대괄호 안쪽, 중괄호 안쪽에서는 불필요한 공백을 사용하지 않습니다.
  • 파일의 끝에는 빈 줄을 추가합니다.

 

아래 예시에서, foo() 함수에서는 if문과 else문에서 항상 공백 4개를 사용하여 들여쓰기하고 있습니다. bar() 함수에서는 키워드와 괄호 사이, 콜론과 문장 사이, 연산자와 피연산자 사이에 항상 공백을 사용하고 있습니다. 또한, 함수 인자 목록에서 각 인자 사이에도 항상 공백을 사용하고 있습니다. baz() 함수에서는 함수 인자 목록에서 각 인자 사이에 항상 공백을 사용하고 있습니다. lst와 dct 변수에서는 괄호 안쪽에서 불필요한 공백을 사용하지 않고 있습니다. 마지막 파일 끝에는 빈줄을 추가했습니다.

 

# 들여쓰기에는 항상 공백 4개를 사용합니다.
def foo():
    if x == 1:
        x += 1
    else:
        x -= 1

# 키워드와 괄호 사이, 콜론과 문장 사이, 연산자와 피연산자 사이에는 항상 공백을 사용합니다.
def bar(x, y, z):
    if x > 0 and y > 0:
        z += x + y
    else:
        z -= x - y

# 함수나 메서드의 인자 목록에서 각 인자 사이에는 항상 공백을 사용합니다.
def baz(a, b, c):
    pass

# 괄호 안쪽이나 대괄호 안쪽, 중괄호 안쪽에서는 불필요한 공백을 사용하지 않습니다.
lst = [1, 2, 3]
dct = {'key': 'value'}
if x in lst:
    pass
if 'key' in dct:
    pass

# 파일의 끝에는 빈 줄을 추가합니다.

 


4. 주석 (Comments)

PEP8에서는 주석(Comments)을 적절하게 사용하여 코드의 가독성을 높이는 것을 권장하고 있습니다. 

 

  • 코드에 대한 주석은 한 줄로 작성하며, # 문자로 시작합니다. 주석은 가능한 한 코드와 같은 줄에 작성하는 것이 좋습니다.
  • 주석은 코드의 의도를 설명하는 데 사용되며, 코드 자체에 대한 설명을 하지 않아야 합니다.
  • 주석은 가능한 한 간결하고 명확해야 하며, 가독성을 향상시키는 데 사용되어야 합니다.
  • 함수나 메서드의 docstring은 세 개의 따옴표(""")로 둘러싸여 작성되어야 합니다.
  • 주석이 코드와 같은 줄에 작성하기 어려운 경우에는, 주석을 코드에서 한 칸 이상 떨어진 위치에 작성할 수 있습니다.

 

아래 예시에서, x 변수에 대한 주석은 변수 할당 코드와 같은 줄에 작성하였습니다. if문에서는 코드 자체가 어떤 일을 수행하는지 설명하는 주석 대신, 코드의 의도를 설명하는 주석을 작성하였습니다. foo() 함수에서는 함수 docstring을 작성하여 함수가 무엇을 하는지에 대한 설명을 제공하였습니다. bar() 함수에서는 주석을 코드에서 한 칸 이상 떨어진 위치에 작성하여 가독성을 높였습니다.

 

# 코드에 대한 주석은 한 줄로 작성하며, # 문자로 시작합니다.
x = 5  # 변수 x에 정수 5를 할당합니다.

# 주석은 코드의 의도를 설명하는 데 사용되며, 코드 자체에 대한 설명을 하지 않아야 합니다.
if x > 0:
    x -= 1  # x가 양수인 경우 1을 뺍니다.

# 함수나 메서드의 docstring은 세 개의 따옴표로 둘러싸여 작성되어야 합니다.
def foo():
    """This function does something."""

# 주석이 코드와 같은 줄에 작성하기 어려운 경우, 주석을 코드에서 한 칸 이상 떨어진 위치에 작성할 수 있습니다.
def bar():
    result = x + y  # x와 y를 더한 결과를 계산합니다.

 


5. 네이밍 컨벤션 (Naming conventions)


PEP8에서는 네이밍 컨벤션(Naming conventions)을 일관되게 적용하여 코드의 가독성을 높이는 것을 권장하고 있습니다.

 

  • 변수, 함수, 메서드의 이름은 소문자로 작성하며, 여러 단어일 경우에는 밑줄(_)로 구분합니다. 예를 들어, my_variable, my_function, my_method와 같이 작성합니다.
  • 클래스의 이름은 첫 글자를 대문자로 작성하며, 여러 단어일 경우에는 각 단어의 첫 글자를 대문자로 작성합니다. 예를 들어, MyClass와 같이 작성합니다.
  • 모듈의 이름은 소문자로 작성하며, 여러 단어일 경우에는 밑줄(_)로 구분합니다. 예를 들어, my_module과 같이 작성합니다.
  • 상수의 이름은 모두 대문자로 작성하며, 여러 단어일 경우에는 밑줄(_)로 구분합니다. 예를 들어, MY_CONSTANT와 같이 작성합니다.

 

아래 예시에서, 변수, 함수, 메서드의 이름은 모두 소문자로 작성되어 있으며, 여러 단어일 경우에는 밑줄(_)로 구분되어 있습니다. 클래스의 이름은 첫 글자를 대문자로 작성되어 있으며, 여러 단어일 경우 각 단어의 첫 글자가 대문자로 작성되어 있습니다. 모듈의 이름은 소문자로 작성되어 있으며, 여러 단어일 경우에는 밑줄(_)로 구분되어 있습니다. 상수의 이름은 모두 대문자로 작성되어 있으며, 여러 단어일 경우에는 밑줄(_)로 구분되어 있습니다.

 

# 변수, 함수, 메서드의 이름은 소문자로 작성하며, 여러 단어일 경우에는 밑줄로 구분합니다.
my_variable = 5

def my_function():
    pass

class MyClass:
    def my_method(self):
        pass

# 모듈의 이름은 소문자로 작성하며, 여러 단어일 경우에는 밑줄로 구분합니다.
import my_module

# 상수의 이름은 모두 대문자로 작성하며, 여러 단어일 경우에는 밑줄로 구분합니다.
MY_CONSTANT = 10

 


6. 임포트 (Imports)

 

PEP8에서는 임포트(Imports)를 적절하게 사용하여 코드의 가독성을 높이는 것을 권장하고 있습니다.

 

  • 모듈을 임포트할 때에는 항상 모듈의 전체 이름을 사용합니다. 예를 들어, import math와 같이 작성합니다.
  • 여러 개의 모듈을 임포트할 때에는 각 모듈을 새 줄에 작성합니다. 이 때, 임포트 순서는 표준 라이브러리 모듈, 서드파티 모듈, 로컬 모듈 순으로 작성합니다.
  • 임포트 문의 순서는 알파벳 순서대로 작성하는 것이 좋습니다.
  • 모듈에서 함수나 클래스를 임포트할 때에는 모듈의 전체 이름을 사용하는 것보다는 함수나 클래스의 이름만을 사용하는 것이 좋습니다. 예를 들어, from math import sqrt와 같이 작성합니다.
  • 함수나 클래스의 이름이 충돌할 가능성이 있는 경우에는, 모듈의 이름을 앞에 붙여서 사용하는 것이 좋습니다. 예를 들어, import numpy as np와 같이 작성합니다.

 

아래 예시에서, math 모듈을 임포트할 때에는 모듈의 전체 이름인 math를 사용하였습니다. 여러 개의 모듈을 임포트할 때에는 각 모듈을 새 줄에 작성하였으며, 순서는 알파벳 순서대로 작성하였습니다. sqrt 함수만을 사용할 경우, math.sqrt 대신 from math import sqrt와 같이 sqrt 함수를 바로 임포트하여 사용하는 것이 좋습니다.

 

# 모듈을 임포트할 때에는 항상 모듈의 전체 이름을 사용합니다.
import math

# 여러 개의 모듈을 임포트할 때에는 각 모듈을 새 줄에 작성합니다.
import os
import sys

# 임포트 문의 순서는 알파벳 순서대로 작성하는 것이 좋습니다.
import numpy
import pandas

# 모듈에서 함수나 클래스를 임포트할 때에는 모듈의 전체 이름을 사용하는 것보다는 함수나 클래스의 이름만을 사용하는 것이 좋습니다.
from math import sqrt

# 함수나 클래스의 이름이 충돌할 가능성이 있는 경우에는, 모듈의 이름을 앞에 붙여서 사용하는 것이 좋습니다.
import numpy as np

 


7. 문자열 인용 (String quotes)

 

PEP8에서는 문자열을 표현할 때, 작은따옴표(')와 큰따옴표(") 중에서 어느 것을 사용해도 상관없지만, 일관성 있는 방법으로 작성하는 것을 권장하고 있습니다. 

 

  • 문자열에 따옴표가 포함된 경우, 문자열을 감싸는 따옴표와 다른 종류의 따옴표를 사용합니다. 예를 들어, "It's a beautiful day"와 같이 작성합니다.
  • 긴 문자열은 여러 줄로 나눠 작성할 수 있습니다. 이 때, 줄 바꿈 문자(\n) 대신에 문자열 리터럴을 여러 줄에 걸쳐 작성할 수 있습니다.
  • 이스케이프 문자를 사용하는 것보다는, 문자열 포맷팅 또는 str.format() 함수를 사용하는 것이 좋습니다.

 

예시에서, "It's a beautiful day"와 같이 문자열에 따옴표가 포함된 경우, 문자열을 감싸는 따옴표와 다른 종류의 따옴표를 사용하였습니다. long_string 변수는 여러 줄에 걸쳐 작성되었으며, 줄 바꿈 문자(\n) 대신에 문자열 리터럴을 여러 줄에 걸쳐 작성하였습니다. 문자열 포맷팅을 사용하여 변수 name과 age의 값을 문자열에 삽입하였습니다.



# 문자열에 따옴표가 포함된 경우, 문자열을 감싸는 따옴표와 다른 종류의 따옴표를 사용합니다.
print("It's a beautiful day")

# 긴 문자열은 여러 줄로 나눠 작성할 수 있습니다.
long_string = ("This is a long string that can be split over multiple lines "
               "without using the newline character.")

# 문자열 포맷팅을 사용하는 것이 좋습니다.
name = "Alice"
age = 25
print("My name is {} and I am {} years old.".format(name, age))

 


8. 표현식과 문장 (Expressions and statements)

PEP8에서는 표현식과 문장(Expressions and statements)을 적절하게 사용하여 코드의 가독성을 높이는 것을 권장하고 있습니다.

  • 각 문장은 가능한 한 짧게 작성하는 것이 좋습니다. 한 줄에는 한 개의 문장만 작성하는 것이 좋습니다.
  • 한 줄에 두 개 이상의 문장을 작성하는 경우, 세미콜론(;)으로 구분할 수 있지만, 가독성을 위해 가능한 한 한 줄에 하나의 문장만 작성하는 것이 좋습니다.
  • 문장의 끝에는 세미콜론(;)을 사용하지 않습니다.
  • 조건문과 반복문에서, if문과 for문에서는 한 줄에 하나의 문장만 작성하는 것이 좋습니다. 이 때, 각 문장은 들여쓰기로 구분합니다.
  • 긴 표현식은 여러 줄로 나눠 작성할 수 있습니다. 이 때, 괄호로 표현식을 둘러싸고, 줄 바꿈 이후에는 추가 들여쓰기를 합니다.

 

예시에서, 첫 번째 예시에서는 각 문장을 가능한 한 짧게 작성하였습니다. 두 번째 예시에서는 한 줄에 두 개 이상의 문장을 작성하지 않고, 세미콜론 대신에 각 문장을 새 줄에 작성하여 가독성을 높였습니다. 세 번째 예시에서는 문장의 끝에 세미콜론을 사용하지 않았습니다. 마지막 예시에서는 긴 표현식을 괄호로 둘러싸고, 줄 바꿈 이후에 추가 들여쓰기를 하여 가독성을 높였습니다.

 

# 각 문장은 가능한 한 짧게 작성하는 것이 좋습니다.
x = 5
y = x + 2

# 한 줄에 두 개 이상의 문장을 작성하는 경우, 세미콜론으로 구분할 수 있지만, 가독성을 위해 가능한 한 한 줄에 하나의 문장만 작성하는 것이 좋습니다.
x = 5; y = x + 2

# 문장의 끝에는 세미콜론을 사용하지 않습니다.
x = 5
y = x + 2

# 조건문과 반복문에서, 한 줄에 하나의 문장만 작성하는 것이 좋습니다.
if x > 0:
    y = x + 1

for i in range(10):
    print(i)


# 긴 표현식은 여러 줄로 나눠 작성할 수 있습니다.
result = (x * y * z
          + x * y * w
          + x * z * w
          - z * w * y)