Posted:      Updated:

PEP8 : Style Guide for Python Code


This document gives coding conventions for the Python code comprising the standard library in the main Python distribution. - Guido van Rossum, Barry Warsaw, Nick Coghlan

PEP8은 Guido van Rossum, Barry Warsaw, Nick Coghlan이 작성한 Python 코드의 코딩 규칙이다. 프로젝트의 자체 코딩 스타일 지침이 있을 경우 해당 프로젝트의 가이드를 우선한다.

PEP8 원문 👉 PEP8

The guidelines provided here are intended to improve the readability of code and make it consistent across the wide spectrum of Python code.

PEP8 원문은 코드의 가독성을 향상시키고 일관성을 유지하기 위해 지침을 제공했다고 밝힌다.

코드 레이아웃 (Code Lay-out)

들여쓰기 (Indentation)

✔ 코드를 여러 줄로 나눠서 작성하는 경우 다음 행과 구분하기 위해 들여쓰기를 한다.
✔ 들여쓰기 한 수준 당 4개의 공백을 사용한다.

# 첫 번째 줄에 인자가 있을 경우 수직 정렬
foo = long_function_name(var_one, var_two,
                         var_three, var_four)

# 첫 번째 줄에 인자가 없을 경우 4칸 들여쓰기
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

잘못 작성할 경우

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)
# 인자를 들여쓰기 하지 않아 다음 행과 구분이 어렵다.

선택 사항

# 4개 공백의 들여쓰기를 하지 않아도 되는 경우

# 다음 행과 구분이 되는 경우
foo = long_function_name(
  var_one, var_two,
  var_three, var_four)

괄호 들여쓰기

✔ 괄호를 닫을 때는 두 가지 방법으로 작성할 수 있다.

# 마지막 줄의 첫번째 요소 아래에 닫기
my_list = [
    1, 2, 3,
    4, 5, 6,
    ]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
    )

# 첫번째 줄의 가장 앞에 닫기
my_list = [
    1, 2, 3,
    4, 5, 6,
]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
)

라인의 최대 길이 (Maximum Line Length)

✔ 모든 줄의 최대 길이는 79자로 제한한다.
✔ 주석이나 docstring 등 구조 제한이 적은 긴 텍스트 블록은 72자로 제한한다.

✔ 길고 여러개를 작성하는 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())

이항연산자 (Binary Operator)

✔ 연산자 앞에서 줄바꿈한다.

income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

빈 줄 (Blank Lines)

✔ 가장 높은 위치의 함수와 클래스 정의는 위 아래에 두 줄을 띄운다.
✔ 클래스 내부의 메소드 정의는 위 아래에 한 줄을 띄운다.
✔ 관련된 기능 그룹을 여유롭게 작성하려면 빈 줄을 추가로 사용할 수 있다.
✔ 관련된 한 줄 묶음 사이에는 빈 줄을 생략할 수 있다. ✔ 논리적 섹션을 나타내기 위해 빈 줄을 사용한다.

소스 파일 인코딩 (Source File Encoding)

✔ 항상 UTF-8(또는 Python 2의 ASCII)을 사용해야 한다.
✔ UTF-8 또는 ASCII을 사용하는 파일에는 인코딩 선언이 없어야 한다.

가져오기 (Imports)

✔ 가져오기는 일반적으로 별도의 줄에 작성한다.

# 올바른 경우
import os
import sys

# 잘못된 경우
import sys, os

# 아래와 같이 작성해도 괜찮음
from subprocess import Popen, PIPE

✔ 가져오기는 항상 파일의 맨 위에 작성한다.
✔ 모듈 주석와 docstring의 바로 뒤에, 모듈 전역변수와 상수 앞에 배치한다.

✔ 아래의 조건을 따라 그룹화해야 한다.

1. 표준 라이브러리 가져오기
2. 관련된 서드 파티 가져오기
3. 로컬 응용 프로그램, 라이브러리 관련 가져오기

✔ 각 가져오기 그룹 사이에는 빈 줄을 표시해야 한다.
✔ 절대 경로를 이용한 가져오기를 권장한다. 가독성이 높고 시스템이 잘못 구성될 경우 오류 메세지 확인이 용이하다.
✔ 상대 경로를 이용한 가져오기는 복잡한 배치를 다룰 때 허용 가능한 대안이다.

✔ 모듈 안의 클래스를 가져올 때는 아래를 사용한다.

from myclass import MyClass
from foo.bar.yourclass import YourClass

✔ 로컬 이름이 충돌하는 경우 아래와 같이 작성한다.

import myclass
import foo.bar.yourclass

그리고 “myclass.MyClass” 와 “foo.bar.yourclass.YourClass”를 사용한다.

✔ 와일드카드 가져오기의 사용은 자제한다.

from <module> import *

Dunder 이름 (Module Level Dunder Names)

✔ Dunder: Double UNDER score, __all__, __author__, __version__와 같이 더블 언더 스코어(__)를 사용하는 것
✔ docstring 뒤에 배치하되 from __future__ 가져오기를 제외한 모든 가져오기문 앞에 배치해야 한다.

"""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

문자열 따옴표 (String Quotes)

✔ 큰따옴표와 작은따옴표가 동일하고 이에 대한 권고를 하지 않는다.
✔ 문자열에 큰따옴표나 작은따옴표가 포함된 경우 백슬래시 사용을 방지하기 위해 다른 문자를 사용하여 가독성을 높인다.
✔ 세 개의 따옴표를 사용할 경우 PEP 257(docstring 규칙)을 준수하기 위해 항상 큰따옴표를 사용해야 한다.

식과 구문의 공백 (Whitespace in Expressions and Statements)

✔ 아래와 같은 경우에 불필요한 공백은 피한다.

괄호, 중괄호, 대괄호 바로 안쪽에는 공백을 사용하지 않는다.

# 올바른 경우
spam(ham[1], {eggs: 2})

# 잘못된 경우
spam( ham[ 1 ], { eggs: 2 } )

콤마(,)와 닫는 괄호 사이에는 공백을 사용하지 않는다.

# 올바른 경우
foo = (0,)

# 잘못된 경우
bar = (0, )

콤마(,) 콜론, 세미콜론 전에는 공백을 사용하지 않는다.

# 올바른 경우
if x == 4: print x, y; x, y = y, x

# 잘못된 경우
if x == 4 : print x , y ; x , y = y , x

슬라이스에서 콜론 양쪽의 공백의 개수, 위치가 같아야 한다. 콜론 양쪽에 매개 변수가 없다면 공백은 생략한다.

# 올바른 경우
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]

# 잘못된 경우
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]

함수 호출 시 인수 목록의 여는 괄호 앞에는 공백을 사용하지 않는다.

# 올바른 경우
spam(1)

# 잘못된 경우
spam (1)

인덱싱, 슬라이싱의 여는 괄호 앞에는 공백을 사용하지 않는다.

# 올바른 경우
dct['key'] = lst[index]

# 잘못된 경우
dct ['key'] = lst [index]

다른 연산자와 정렬하기 위한 공백을 사용하지 않는다.

# 올바른 경우
x = 1
y = 2
long_variable = 3

# 잘못된 경우
x             = 1
y             = 2
long_variable = 3

기타 권장 사항 (Other Recommendations)

✔ 어느 곳에서도 후행공백을 피한다.
✔ 아래 이진 연산자는 공백으로 양쪽을 둘러싼다.

할당연산자 (=)
증감연산자 (+=, -=)
비교연산자 (==, <, >, !=, <>, <=, >=, in, not in, is, is not)
불린연산자 (and, or, not)

✔ 우선순위가 다른 연산자를 사용하는 경우 우선순위가 가장 낮은 연산자 주위에 공백을 추가한다. 두개 이상의 공백을 사용하지는 않는다. 이진연산자의 양쪽에는 동일한 여백이 있어야 한다.

# 올바른 경우
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)

# 잘못된 경우
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)

✔ 함수 주석은 콜론(:)에 대해 일반 규칙을 적용하며, -> 화살표 주변에 공백을 항상 사용한다.

# 올바른 경우
def munge(input: AnyStr): ...
def munge() -> PosInt: ...

# 잘못된 경우
def munge(input:AnyStr): ...
def munge()->PosInt: ...

✔ 함수 주석을 사용하지 않을 때 매개변수의 기본값을 나타낼 때 = 기호 주변에 공백을 사용하지 않는다.

# 올바른 경우
def complex(real, imag=0.0):
    return magic(r=real, i=imag)

# 잘못된 경우
def complex(real, imag = 0.0):
    return magic(r = real, i = imag)

✔ 함수 주석과 매개변수의 기본값을 결합해서 사용할 때는 = 기호 주위에 공백을 사용한다.

# 올바른 경우
def munge(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...

# 잘못된 경우
def munge(input: AnyStr=None): ...
def munge(input: AnyStr, limit = 1000): ...

✔ 한 줄에 여러 구문을 사용하지 않는다.

# 올바른 경우
if foo == 'blah':
    do_blah_thing()
do_one()
do_two()
do_three()

# 잘못된 경우
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()

if, for, while 구문에서 바디가 짧을 때 가끔 같은 줄에 작성하는 것은 괜찮지만, 여러 줄을 이렇게 작성하지는 않는다.

# 잘못된 경우
if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t < 10: t = delay()

# 매우 잘못된 경우
if foo == 'blah': do_blah_thing()
else: do_non_blah_thing()

try: something()
finally: cleanup()

do_one(); do_two(); do_three(long, argument,
                         list, like, this)

if foo == 'blah': one(); two(); three()

후행 쉼표를 사용하는 경우 (When to Use Trailing Commas)

✔ 후행 쉼표는 선택 사항이지만, 한 요소의 튜플을 만들 때는 필수 사항이다. 명확한 구별을 위해 괄호를 사용한다.

# 올바른 경우
FILES = ('setup.cfg',)

# 잘못된 경우
FILES = 'setup.cfg',

✔ 후행 쉼표를 사용하면 나중에 값, 인수 또는 항목의 목록이 확장될 수 있다고 예상할 수 있다. 한 줄에 한 값만 작성하고 후행 쉼표를 사용한다. 닫는 구분 기호(),], })는 다음 줄에 작성한다.

# 올바른 경우
FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           ) 

# 잘못된 경우
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)

주석 (Comments)

✔ 코드와 맞지 않는 주석은 항상 좋지 않다. 코드 변경 시 항상 주석을 변경한다.
✔ 주석은 완전한 문장이어야 한다. 소문자로 시작하는 식별자가 아닌 한 대문자를 사용해야 한다.
✔ 블록 코멘트는 일반적으로 각 문장이 마침표로 끝나는 완전한 문장으로 구성된 하나 이상의 단락으로 구성한다.
✔ 여러 문장으로 된 주석에서는 마지막 문장을 제외하고 문장 끝 마침표 뒤에 두 개의 공백을 사용해야 한다.
✔ 자신이 작성하는 언어를 사용하는 다른 사용자가 의견을 명확하고 쉽게 이해할 수 있도록 확인한다.
✔ 비영어권 국가라도 가능하면 영어로 주석을 사용한다.

블록 주석 (Block Comments)

✔ 일반적으로 뒤에 오는 코드에 적용되며 해당 코드와 동일한 수준으로 들여쓰기한다.
✔ 블록 주석의 각 줄은 # 및 단일 공백으로 시작한다.
✔ 블록 주석 내부의 단락은 # 하나를 포함하는 행으로 구분한다.

인라인 주석 (Inline Comments)

✔ 인라인 주석은 조금만 사용한다.
✔ 인라인 주석은 명령문과 같은 줄에 있는 주석이다. 명령문에서 두 개 이상의 공백으로 분리한 후 #과 단일 공백으로 시작한다.
✔ 인라인 주석은 불필요하며 주의를 산만하게 한다.

# 이렇게 사용하지 않는다.
x = x + 1                 # Increment x

# 아래와 같은 경우는 때때로 유용하다.
x = x + 1                 # Compensate for border

닥스트링 (Documentation Strings)

✔ 닥스트링에 대한 규칙은 PEP257을 참고한다.
✔ 모든 공개 모듈, 함수, 클래스, 메소드에 대해 닥스트링을 작성한다.
✔ 비공개 메소드에는 닥스트링이 필요하지는 않지만 메소드의 기능을 설명하는 주석이 있어야 한다. 이 주석은 def 라인 뒤에 작성한다.
✔ 여러 줄로 구성된 닥스트링에서 """은 단독으로 작성해야 한다.

"""Return a foobang

Optional plotz says to frobnicate the bizbaz first.
"""

✔ 닥스트링을 한 줄로 작성한다면 """를 같은 줄에 작성한다.

"""Return an ex-parrot."""

이름 작성 규칙 (Naming Conventions)

Python 라이브러리의 명명 규칙은 약간 엉망이므로 완전히 일관성을 가지지 않는다.
✔ 그럼에도 불구하고 현재 권장되는 명명 표준이 있다.
✔ 새로운 모듈 및 패키지(프레임워크 포함)는 이러한 표준에 따라 작성되어야 하지만, 기존 라이브러리 스타일이 다른 경우 내부적으로 일관성 있게 작성한다.

우선 원칙 (Overriding Principle)

✔ API의 공개 부분으로 보여지는 이름은 실행 결과보다는 사용법을 반영하는 규칙을 따라야 한다.

피해야 할 이름 (Names to Avoid)

l(소문자 el), O(대문자 oh), I(대문자 eye)를 단일 문자 변수 이름으로 사용하지 않는다.
l(소문자 el)을 사용하고자 할 때는 L(대문자 el)을 사용한다.

ASCII 호환성 (ASCII Compatibility)

✔ 표준 라이브러리에서 사용되는 식별자는 ASCII와 호환되어야 한다.

패키지 및 모듈의 이름 (Package and Module Names)

✔ 모듈은 소문자로 된 짧은 이름을 가져야 한다.
✔ 모듈의 가독성을 높이기 위해 언더스코어(_)가 사용될 수 있다.
✔ 패키지에서 밑줄 사용은 권장되지 않으며 소문자로 된 짧은 이름을 가져야 한다.
✔ C또는 C++로 작성된 확장 모듈에 상위 레벨(객체 지향적인) 인터페이스를 제공하는 Python 모듈이 포함되어 있으면 C/C++ 모듈에 선행 밑줄(언더스코어)를 작성한다.

클래스 이름 (Class Names)

✔ 클래스 이름은 일반적으로 CapWords 규칙을 사용해야 한다.

전역 변수 이름 (Global Variable Names)

✔ 하나의 모듈 내에서만 사용하는 것을 권장한다.
✔ 함수에 대한 작성 규칙과 거의 같다.

함수 및 변수 이름 (Function and Variable Names)

✔ 함수 이름은 소문자여야 하며 가독성을 높이기 위해 필요한 경우 밑줄로 단어를 구분한다.
✔ 변수 이름은 함수 이름과 동일한 규칙을 적용한다.

상수 (Constants)

✔ 일반적으로 모듈 수준에서 정의한다.
✔ 모두 대문자로 작성하며 밑줄(_)로 단어를 구분한다.


📝 참조
블로그 EG공간
블로그 codechacha

댓글남기기