본문 바로가기
프로그래밍/Python

PEP 8 - Style Guide for Python Code 정리 / Python Code 일관성, 가독성 높이며 작성하기

by hi-rachel 2022. 11. 3.
 💡 이 글은 PEP 8 – Python 코드용 스타일 가이드(https://peps.python.org/pep-0008/)를 보고 새롭게 안 사실을 공부하며 정리한 내용입니다. 영어를 한국어 번역을 사용해 문맥이 이상한 부분이 있을 수 있습니다. 참고만 하시고 실제로 원문을 참고하시길 바랍니다.

 

A Foolish Consistency is the Hobgoblin of Little Minds

본격적으로 문서를 읽기 전 쓰여 있는 말.

어리석은 일관성은 작은 마음의 홉고블린이다.’ 무슨 뜻인지 궁금해 찾아보았다.

 

에머슨의 인용문은 한 줄 이상으로 가장 잘 이해됩니다. “어리석은 일관성은 작은 정치가와 철학자와 신들이 숭배하는 작은 마음의 홉고블린입니다. 일관성이 있으면 위대한 영혼은 할 일이 없습니다. 그는 벽에 자신의 그림자에 관심을 가질 수도 있습니다. 지금 생각하는 것을 어려운 말로 말하고 내일 내일 생각하는 것을 다시 어려운 말로 말하십시오. 비록 오늘 말한 모든 것과 모순되지만 말입니다. — '아, 그럼 오해하실 텐데요.' — 그렇다면 오해를 받는 것이 그렇게 나쁜 일입니까? 피타고라스와 소크라테스, 예수, 루터, 코페르니쿠스, 갈릴레오, 뉴턴, 그리고 육신을 취한 모든 순수하고 지혜로운 영혼들이 오해를 받았습니다. 위대하다는 것은 오해를 받는 것이다.”

현실은 세상은 항상 변하고 있으며 단순히 사회의 기대에 순응하는 것만으로도 삶의 급증과 유희에서 단절되고 평범함 속에서 삶을 시들고 물들인다는 것입니다. 그러나 에머슨은 내가 할 수 있는 것보다 훨씬 더 유창하게 이것을 말했습니다.

(출처_영어로 읽기 : https://qr.ae/pvzSYl)

 

“To be great is to be misunderstood.”

개발 공부하다가 영어 본문을 읽어야 할 때가 많은데 멋진 점이 바로 이런 게 아닐까! 정말 멋있는 표현이다.

 

Python 코드용 스타일 가이드에 적용되는 의미는 제공된 이 지침이 코드의 가독성을 개선하고 광범위한 Python 코드에서 일관성을 유지하기 위한 것이지만, 이 “가독성이 중요”하다는 것을 말한다. 스타일 가이드와의 일관성이 중요하지만, 프로젝트 내에서 일관성이 더 중요하다고 말한다. 하나의 모듈 또는 기능 내에서의 일관성이 가장 중요하다.

때에 따라 최선의 판단을 내려야 한다!

 

지침에 대한 자세한 예시는 [참고]

 

특히: 이 PEP를 준수하기 위해 이전 버전과의 호환성을 깨뜨리지 마십시오!

※ 특정 지침을 무시해야 하는 다른 좋은 이유:

  1. 지침을 적용하면 이 PEP를 따르는 코드를 읽는 데 익숙한 사람이라도 코드를 덜 읽을 수 있습니다.
  2. 코드를 깨뜨리는 주변 코드와 일관성을 유지하기 위해(아마도 역사적인 이유일 수 있음) – 이것은 다른 사람의 엉망을 정리할 기회이기도 합니다(진정한 XP 스타일에서).
  3. 문제의 코드는 가이드라인의 도입보다 앞선 것이며 해당 코드를 수정할 다른 이유가 없기 때문입니다.
  4. 코드가 스타일 가이드에서 권장하는 기능을 지원하지 않는 이전 버전의 Python과 계속 호환되어야 하는 경우.

 


 

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

들여 쓰기(Indentation)

  • 들여 쓰기 수준당 4개의 공백을 사용합니다.
  • 연속 라인은 괄호, 대괄호 및 중괄호 내부를 결합하는 Python의 암시적 라인을 사용하거나 매달린 들여 쓰기를 사용하여 래핑 된 요소를 수직으로 정렬해야 합니다. 내어 쓰기를 사용할 때 다음 사항을 고려해야 합니다. 첫 번째 줄에는 인수가 없어야 하며 연속된 줄로 자신을 명확하게 구분하기 위해 추가 들여 쓰기를 사용해야 합니다.
# Correct:

# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
                         var_three, var_four)

# Add 4 spaces (an extra level of indentation) to distinguish arguments from the rest.
def long_function_name(
	    var_one, var_two, var_three,
        var_four):
    print(var_one)

# Hanging indents should add a level.
foo = long_function_name(
    var_one, var_two,
    var_three, var_four)
# Wrong:
# Arguments on first line forbidden when not using vertical alignment.
foo = long_function_name(var_one, var_two,
    var_three, var_four)

# Further indentation required as indentation is not distinguishable.def long_function_name(
    var_one, var_two, var_three,
    var_four):
    print(var_one)

 

📌 들여 쓰기 줄을 맞춘다.

 

  • 연속 행의 경우 4칸 규칙은 선택 사항입니다.
# Hanging indents *may* be indented to other than 4 spaces.
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',
)

 

📌 그동안 Python을 작성할 때 편하게 Tab만 사용했는데 문서를 읽어보니 4개의 공백이 권장되고 있다. 밑에 내용처럼 이미 Tab으로만 들여 쓰기 된 코드는 일관성을 유지하기 위해 사용되어야 하지만 앞으로 새롭게 작성할 때는 권장사항대로 사용해야겠다.

 

탭 또는 공백(Tabs or Spaces)?

  • 공백은 선호하는 들여 쓰기 방법입니다.
  • 탭은 이미 탭으로 들여 쓰기 된 코드와 일관성을 유지하기 위해서만 사용해야 합니다.
  • Python은 들여 쓰기를 위해 탭과 공백을 혼합하는 것을 허용하지 않습니다.

 

최대 라인 길이

  • 모든 줄은 최대 79자로 제한한다.
  • 구조적 제한(독스트링 또는 주석)이 적은 긴 텍스트 블록의 경우 줄 길이는 72자로 제한되어야 합니다.

 

이진 연산자(Binary Operator) 전후에 줄 바꿈 해야 하나?

# Wrong:
# operators sit far away from their operands
income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)
# Correct:
# easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

 

📌 2번째 이진 연산자 줄 바꿈 예시가 훨씬 깔끔해 보인다!

(Python 코드에서 규칙이 로컬에서 일관되는 한 이항 연산자 앞이나 뒤에 중단할 수 있습니다.)

 


 

기타 권장 사항

  • 할당(=), 증대 할당_augmented assignment(+=, -= 등), 비교(==, <, >,!=, <>, <=, >=, in, not in, is, is not), Booleans (and, or, not)과 같은 이항 연산자항상 쪽에 단일 공백으로 둘러쌉니다.
  • 우선순위가 다른 연산자를 사용하는 경우 우선 순위가 가장 낮은 연산자 주위에 공백을 추가하는 것이 좋습니다. 자신의 판단을 사용하십시오. 그러나 두 개 이상의 공백을 사용하지 마십시오. 이항 연산자의 양쪽에 항상 같은 양의 공백이 있어야 합니다.
# Correct:
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)
# Wrong:
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)

 

📌 그동안 연산자 사이는 다 공백을 두었는데 할당, 비교, 불리언 관련 연산자 양쪽에 공백을 주고, 우선순위가 낮은 연산자에 공백 추가! 나머지는 붙여 써야겠다.

 

  • 키워드 인수를 나타낼 때 또는 주석 없는 함수 매개변수의 기본값을 나타낼 때 = 기호 주변에 공백을 사용하지 마십시오.
# Correct:
def complex(real, imag=0.0):
return magic(r=real, i=imag)
# Wrong:
def complex(real, imag = 0.0):
return magic(r = real, i = imag)

 

  • 그러나 인수 주석(argument annotation)을 기본값과 결합할 때 = 기호 주위에 공백을 사용하십시오.
# Correct:
def munge(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
# Wrong:
def munge(input: AnyStr=None): ...
def munge(input: AnyStr, limit = 1000): ...

 

  • 때로는 작은 본문과 함께 if/for/while을 같은 줄에 넣는 것이 괜찮지만 다중 절 구문에서는 절대 이 작업을 수행하지 마십시오. 또한 그러한 긴 줄을 접는 것은 피하십시오!

Rather not:

# Wrong:
if foo == 'blah': do_blah_thing()
for xin lst: total += x
while t < 10: t = delay()

Definitely not:

# Wrong:
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()Definitely not:

 

 


후행 쉼표(Trailing Commas)를 사용해야 하는 경우

  • 후행 쉼표는 한 요소의 튜플을 만들 때 필수임을 제외하고 일반적으로 선택 사항입니다. 명확성을 위해 후자를 (기술적으로 중복되는) 괄호로 묶는 것이 좋습니다.
# Correct:
FILES = ('setup.cfg',)
# Wrong:
FILES = 'setup.cfg',

 

  • 후행 쉼표가 중복되면 버전 제어 시스템이 사용될 때, 값 목록, 인수 또는 가져온 항목이 시간이 지남에 따라 확장될 것으로 예상되는 경우에 종종 유용합니다. 패턴은 각 값(등)을 한 줄에 단독으로 넣고 항상 후행 쉼표를 추가하고 다음 줄에 닫는 괄호/대괄호/중괄호를 추가하는 것입니다. 그러나 닫는 구분 기호와 같은 줄에 후행 쉼표를 사용하는 것은 이치에 맞지 않습니다(위의 싱글톤 튜플(singleton tuples)의 경우 제외).
# Correct:
FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           )
# Wrong:
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)

 


 

주석(Comments)

  • 코드와 모순되는 주석은 주석이 없는 것보다 나쁩니다. 코드가 변경될 때 항상 주석을 최신 상태로 유지하는 데 우선순위를 두십시오!
  • 주석은 완전한 문장이어야 합니다. 소문자로 시작하는 식별자가 아닌 경우 첫 번째 단어는 대문자여야 합니다(식별자의 대소문자를 변경하지 마십시오!).
  • 블록 주석은 일반적으로 완전한 문장으로 구성된 하나 이상의 단락으로 구성되며 각 문장은 마침표로 끝납니다.
  • 여러 문장으로 된 주석에서는 마지막 문장을 제외하고 문장 끝 마침표 뒤에 두 개의 공백을 사용해야 합니다.
  • 귀하가 작성하는 언어를 사용하는 다른 사용자가 귀하의 의견을 명확하고 쉽게 이해할 수 있는지 확인하십시오.
  • 비영어권 국가의 Python 코더: 귀하의 언어를 사용하지 않는 사람들이 코드를 읽을 수 없다는 120% 확신이 없다면 영어로 의견을 작성하십시오.

 

인라인 댓글(Inline Comments)

  • 인라인 주석은 아껴서 사용하십시오.
  • 인라인 주석은 명령문과 같은 줄에 있는 주석입니다. 인라인 주석은 명령문에서 두 개 이상의 공백으로 분리되어야 합니다. # 및 단일 공백으로 시작해야 합니다.
  • 인라인 주석은 불필요하며 명백하게 명시되어 있으면 실제로 주의를 산만하게 합니다. 다음과 같이 하지 마십시오.
# Wrong:
x = x + 1                 # Increment x
# Correct:
x = x + 1                 # Compensate for border

 

문서 문자열(Documentation Strings)

  • 모든 공개 모듈, 함수, 클래스 및 메서드에 대한 독스트링을 작성합니다. 비공개 메서드에는 독스트링이 필요하지 않지만 메서드가 하는 일을 설명하는 주석이 있어야 합니다. 이 주석은 줄 뒤에 나타나야 합니다 def.
  • PEP 257 은 좋은 독스트링 규칙을 설명합니다. 가장 중요한 것은 여러 줄 독스트링(docstring)을 끝내는 """는 그 자체로 한 줄에 있어야 한다는 것입니다.
"""Return a foobang

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

 

  • 하나의 라이너 독스트링의 경우 닫는 """부분을 같은 줄에 유지하세요.
"""Return an ex-parrot."""

 


 

명명 규칙(Naming Convention)

  • 명명 스타일 참고: CapWords에서 두문자어(약자)를 사용할 때 두문자어의 모든 문자를 대문자로 사용하십시오. 따라서 HTTPServerError는 HttpServerError보다 낫습니다.

 

유형 변수 이름(Type Variable Names)

  • PEP 484에 도입된 유형 변수의 이름은 일반적으로 짧은 이름인 T, AnyStr, Num을 선호하는 CapWords를 사용해야 합니다. 다음과 같이 공변(covariant = (다른 변인과) 함께 변하는) 또는 반변(contravariant) 동작을 선언하는 데 사용되는 변수에 접미사 _co 또는 _contra를 추가하는 것이 좋습니다.
from typing import TypeVar

VT_co = TypeVar('VT_co', covariant=True)
KT_contra = TypeVar('KT_contra', contravariant=True)

 


 

프로그래밍 권장사항

  • not ... is 대신 is not 연산자를 사용하십시오. 두 식은 기능적으로 동일하지만 전자가 더 읽기 쉽고 선호됩니다.
# Correct:
if foo is not None:
# Wrong:
if not foo is None:

 

  • 접두사 또는 접미사를 확인하려면 문자열 슬라이싱(string slicing) 대신 ''. startswith(), ''. endswith()을 사용하십시오.
  • startswith() 및 endswith()는 더 깨끗하고 오류가 덜 발생합니다.
# Correct:
if foo.startswith('bar'):
# Wrong:
if foo[:3] == 'bar':

 

  • 중요한 후행 공백에 의존하는 문자열 리터럴을 작성하지 마십시오. 이러한 후행 공백은 시각적으로 구별할 수 없으며 일부 편집자(또는 최근에는 reindent.py)가 이를 자릅니다.
  • ==을 사용하여 boolean 값을 True 또는 False와 비교하지 마십시오.
# Correct:
if greeting:
# Wrong:
if greeting == True:

Worse :

# Wrong:
if greeting is True:

 

 

더 공부하러 가기

https://peps.python.org/pep-0008/#should-a-line-break-before-or-after-a-binary-operator

 

PEP 8 – Style Guide for Python Code | peps.python.org

PEP 8 – Style Guide for Python Code Author: Guido van Rossum , Barry Warsaw , Nick Coghlan Status: Active Type: Process Created: 05-Jul-2001 Post-History: 05-Jul-2001, 01-Aug-2013 Table of Contents This document gives coding conventions for the Python co

peps.python.org

 

 

📚 # TIL :
""" 몰랐던 Python 쓰는 방법들이 많이 적혀있다. 초보 입장에서는 굉장히 새롭다.
한번 꼭 문서를 읽어보면 파이썬 코드의 가독성을 높일 수 있다!
일관된 규칙을 따르는 것이 다른 사람과의 협업에서도 참 유용할 것이다.
여기에 적은 내용 외에도 추가적인 내용이 원문에 많이 적혀있다. 직접 읽어보자!
명명 규칙은 추후 따로 정리해야겠다.
"""

 

 

- 혹시 잘못된 내용이 있으면 피드백 주시면 수정하겠습니다 : )