Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 8 – 파이썬 코드 스타일 가이드

Author:
Guido van Rossum <guido at python.org>, Barry Warsaw <barry at python.org>, Alyssa Coghlan <ncoghlan at gmail.com>
Status:
Active
Type:
Process
Created:
05-Jul-2001
Post-History:
05-Jul-2001, 01-Aug-2013

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

소개

이 문서는 메인 파이썬 배포판의 표준 라이브러리를 구성하는 파이썬 코드에 대한 코딩 규약을 제공합니다. Python 구현체에서 C 코드에 대한 스타일 가이드라인을 설명하는 동반 정보성 PEP인 Python 구현체의 C 코드에 대한 스타일 가이드라인도 참고하십시오.

이 문서와 PEP 257(독스트링 규약)은 Guido의 원래 파이썬 스타일 가이드 에세이를 바탕으로, Barry의 스타일 가이드 [2]에서 일부 내용을 추가하여 각색되었습니다.

이 스타일 가이드는 추가적인 규약이 확인되고 언어 자체의 변화로 인해 과거 규약이 더 이상 사용되지 않게 됨에 따라 시간이 지나면서 발전합니다.

많은 프로젝트는 자체적인 코딩 스타일 가이드라인을 가지고 있습니다. 충돌이 발생하는 경우, 해당 프로젝트별 가이드가 그 프로젝트에 대해 우선합니다.

어리석은 일관성은 옹졸한 마음의 도깨비입니다

Guido의 핵심 통찰 중 하나는 코드가 작성되는 것보다 훨씬 더 자주 읽힌다는 것입니다. 여기에 제공된 가이드라인은 코드의 가독성을 향상시키고 다양한 파이썬 코드 전반에 걸쳐 일관성을 유지하기 위한 것입니다. “가독성이 중요하다”고 PEP 20에서 말합니다.

스타일 가이드는 일관성에 관한 것입니다. 이 스타일 가이드와의 일관성은 중요합니다. 프로젝트 내에서의 일관성이 더 중요합니다. 하나의 모듈이나 함수 내에서의 일관성이 가장 중요합니다.

하지만 언제 일관성을 깨야 하는지 아는 것도 중요합니다 – 스타일 가이드의 권장 사항이 적용되지 않는 경우도 있기 때문입니다. 확신이 서지 않을 때는 최선의 판단을 따르십시오. 다른 예시들을 살펴보고 가장 좋아 보이는 것을 결정하십시오. 그리고 주저하지 말고 물어보십시오!

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

특정 지침을 무시해도 좋은 몇 가지 이유는 다음과 같습니다:

  1. 이 PEP를 따르는 코드를 읽는 데 익숙한 사람에게조차 그 지침을 적용하면 코드의 가독성이 떨어지는 경우입니다.
  2. 지침을 어기고 있는 주변 코드와의 일관성을 유지하기 위한 경우입니다(아마 역사적인 이유 때문일 것입니다) – 다만 이는 다른 사람이 남긴 지저분한 코드를 정리할 기회이기도 합니다(진정한 XP 방식으로).
  3. 해당 코드가 그 지침이 도입되기 이전부터 존재했고, 그 코드를 수정할 다른 이유가 없는 경우입니다.
  4. 코드가 스타일 가이드에서 권장하는 기능을 지원하지 않는 이전 버전의 파이썬과 호환성을 유지해야 하는 경우입니다.

코드 레이아웃

들여쓰기

들여쓰기 단계마다 4칸의 공백을 사용하십시오.

연속줄은 괄호, 대괄호, 중괄호 안에서 파이썬의 암묵적 줄 결합을 사용하여 줄바꿈된 요소를 수직으로 정렬하거나, hanging indent[1]를 사용하여 정렬해야 합니다. hanging indent를 사용할 때는 다음 사항을 고려해야 합니다. 첫 줄에는 인자를 두지 않아야 하며, 연속줄임을 명확히 구분하기 위해 추가 들여쓰기를 사용해야 합니다:

# 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)

if문의 조건 부분이 여러 줄에 걸쳐 작성해야 할 만큼 길 때, 두 글자 키워드(즉 if)와 공백 하나, 그리고 여는 괄호의 조합이 여러 줄로 된 조건식의 이후 줄에 자연스러운 4칸 들여쓰기를 만든다는 점에 주목할 만합니다. 이는 if문 내부에 중첩된 들여쓰기된 코드 블록과 시각적으로 충돌할 수 있는데, 이 또한 자연스럽게 4칸 들여쓰기가 되기 때문입니다. 이 PEP는 이러한 조건식 줄을 if문 내부의 중첩된 코드 블록과 시각적으로 더 구분할지(또는 구분할지 여부조차) 명시적인 입장을 취하지 않습니다. 이러한 상황에서 허용되는 선택지에는 다음이 포함되지만 이에 국한되지 않습니다:

# No extra indentation.
if (this_is_one_thing and
    that_is_another_thing):
    do_something()

# Add a comment, which will provide some distinction in editors
# supporting syntax highlighting.
if (this_is_one_thing and
    that_is_another_thing):
    # Since both conditions are true, we can frobnicate.
    do_something()

# Add some extra indentation on the conditional continuation line.
if (this_is_one_thing
        and that_is_another_thing):
    do_something()

(이항 연산자 앞에서 줄을 바꿀지 뒤에서 줄을 바꿀지에 대한 논의는 아래를 참고하십시오.)

여러 줄에 걸친 구문의 닫는 중괄호/대괄호/소괄호는 다음과 같이 리스트의 마지막 줄에서 첫 번째 공백이 아닌 문자 아래에 맞춰 정렬할 수 있습니다:

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',
)

탭인가 스페이스인가?

스페이스가 선호되는 들여쓰기 방법입니다.

탭은 이미 탭으로 들여쓰기된 코드와의 일관성을 유지하기 위해서만 사용해야 합니다.

파이썬은 들여쓰기에 탭과 스페이스를 혼용하는 것을 허용하지 않습니다.

최대 줄 길이

모든 줄은 최대 79자로 제한하십시오.

구조적 제약이 적은 긴 텍스트 블록(독스트링이나 주석)의 경우, 줄 길이는 72자로 제한해야 합니다.

필요한 에디터 창 너비를 제한하면 여러 파일을 나란히 열어 놓을 수 있으며, 두 버전을 인접한 열에 나타내는 코드 리뷰 도구를 사용할 때도 잘 작동합니다.

대부분의 도구에서 기본 줄바꿈은 코드의 시각적 구조를 해쳐 이해를 더 어렵게 만듭니다. 이 제한은 도구가 줄을 바꿀 때 마지막 열에 표시 문자를 넣더라도, 창 너비가 80으로 설정된 편집기에서 줄바꿈이 일어나지 않도록 선택된 것입니다. 일부 웹 기반 도구는 동적 줄바꿈을 아예 제공하지 않을 수 있습니다.

일부 팀은 더 긴 줄 길이를 강하게 선호합니다. 이 문제에 대해 합의에 이를 수 있는 팀이 전적으로 또는 주로 유지 관리하는 코드라면, 주석과 독스트링을 여전히 72자에서 줄바꿈하는 한 줄 길이 제한을 99자까지 늘려도 괜찮습니다.

파이썬 표준 라이브러리는 보수적이며, 줄을 79자로(그리고 독스트링/주석은 72자로) 제한할 것을 요구합니다.

긴 줄을 줄바꿈하는 데 선호되는 방법은 소괄호, 대괄호, 중괄호 안에서 파이썬의 암시적 줄 연속을 사용하는 것입니다. 긴 줄은 표현식을 소괄호로 감싸서 여러 줄로 나눌 수 있습니다. 줄 연속에 백슬래시를 사용하기보다는 이 방법을 우선적으로 사용해야 합니다.

백슬래시가 여전히 적절한 경우도 있습니다. 예를 들어, 길고 여러 개의 with 문은 파이썬 3.10 이전에는 암시적 연속을 사용할 수 없었으므로, 이런 경우에는 백슬래시가 허용되었습니다:

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())

(이러한 여러 줄에 걸친 with 문의 들여쓰기에 대한 추가적인 논의는 앞서 나온 multiline if-statements 를 참고하십시오.)

또 다른 사례는 assert 문입니다.

이어지는 줄을 적절하게 들여쓰기하십시오.

이항 연산자 앞에서 줄을 바꿔야 합니까, 아니면 뒤에서 바꿔야 합니까?

수십 년 동안 권장되던 스타일은 이항 연산자 뒤에서 줄을 바꾸는 것이었습니다. 하지만 이는 두 가지 방식으로 가독성을 해칠 수 있습니다: 연산자들이 화면상의 서로 다른 열에 흩어지는 경향이 있고, 각 연산자가 자신의 피연산자에서 멀어져 이전 줄로 옮겨지게 됩니다. 여기서는 어떤 항목이 더해지고 어떤 항목이 빼지는지를 파악하기 위해 눈이 추가로 작업을 해야 합니다:

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

이러한 가독성 문제를 해결하기 위해, 수학자들과 그들의 출판사는 반대되는 관례를 따릅니다. 도널드 커누스는 자신의 Computers and Typesetting 시리즈에서 전통적인 규칙을 다음과 같이 설명합니다: “단락 안의 수식은 항상 이항 연산과 관계 뒤에서 줄을 바꾸지만, 별도로 표시된 수식은 항상 이항 연산 앞에서 줄을 바꾼다” [3].

수학의 전통을 따르면 대체로 더 읽기 쉬운 코드가 만들어집니다:

# Correct:
# easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

파이썬 코드에서는 지역적으로 관례가 일관되게 유지되는 한, 이항 연산자 앞이나 뒤에서 줄을 바꾸는 것이 허용됩니다. 새 코드에는 커누스의 스타일이 권장됩니다.

빈 줄

최상위 함수와 클래스 정의는 빈 줄 두 개로 둘러싸십시오.

클래스 내부의 메서드 정의는 빈 줄 하나로 둘러쌉니다.

관련된 함수들의 그룹을 구분하기 위해 (드물게) 추가로 빈 줄을 사용할 수 있습니다. 서로 관련된 한 줄짜리 코드들(예: 일련의 더미 구현) 사이에서는 빈 줄을 생략할 수 있습니다.

함수 내에서는 논리적인 구역을 나타내기 위해 빈 줄을 드물게 사용하십시오.

파이썬은 control-L(즉 ^L) 폼 피드 문자를 공백으로 인정합니다; 많은 도구가 이 문자를 페이지 구분자로 취급하므로, 이를 사용하여 파일 내에서 서로 관련된 섹션들의 페이지를 구분할 수 있습니다. 참고로, 일부 편집기와 웹 기반 코드 뷰어는 control-L을 폼 피드로 인식하지 못하고 그 자리에 다른 글리프를 표시할 수 있습니다.

소스 파일 인코딩

핵심 Python 배포판의 코드는 항상 UTF-8을 사용해야 하며, 인코딩 선언을 가지지 않아야 합니다.

표준 라이브러리에서는 비UTF-8 인코딩을 테스트 목적으로만 사용해야 합니다. 비ASCII 문자는 가급적 지명과 인명을 표기할 때만, 아껴서 사용하십시오. 비ASCII 문자를 데이터로 사용하는 경우, z̯̯͡a̧͎̺l̡͓̫g̹̲o̡̼̘ 와 같이 시끄러운 유니코드 문자나 바이트 순서 표시(byte order mark)는 피하십시오.

Python 표준 라이브러리의 모든 식별자는 ASCII 문자만으로 이루어진 식별자를 사용해야 하며(MUST), 실현 가능한 경우 영어 단어를 사용해야 합니다(SHOULD)(많은 경우 영어가 아닌 약어나 전문 용어가 사용됩니다).

전 세계 사용자를 대상으로 하는 오픈소스 프로젝트도 이와 유사한 정책을 채택할 것을 권장합니다.

Import

  • Import는 보통 한 줄에 하나씩 작성해야 합니다:
    # Correct:
    import os
    import sys
    
    # Wrong:
    import sys, os
    

    다만 다음과 같이 작성하는 것은 괜찮습니다:

    # Correct:
    from subprocess import Popen, PIPE
    
  • Import는 항상 모듈에 대한 주석과 독스트링(docstring) 바로 다음, 모듈의 전역 변수나 상수보다 앞에 위치시킵니다.

    Import는 다음 순서로 그룹화해야 합니다:

    1. 표준 라이브러리 import.
    2. 관련된 서드파티 import.
    3. 로컬 애플리케이션/라이브러리 관련 import.

    각 import 그룹 사이에는 빈 줄을 하나 넣어야 합니다.

  • 절대 임포트는 일반적으로 더 읽기 쉽고, 임포트 시스템이 잘못 구성된 경우(예를 들어 패키지 내부의 디렉터리가 sys.path에 올라가는 경우) 더 잘 동작하는 경향이 있으므로(또는 적어도 더 나은 오류 메시지를 제공하므로) 권장됩니다:
    import mypkg.sibling
    from mypkg import sibling
    from mypkg.sibling import example
    

    그러나 복잡한 패키지 레이아웃을 다룰 때, 특히 절대 임포트를 사용하면 불필요하게 장황해지는 경우에는, 명시적 상대 임포트가 절대 임포트의 받아들일 만한 대안입니다:

    from . import sibling
    from .sibling import example
    

    표준 라이브러리 코드는 복잡한 패키지 레이아웃을 피하고 항상 절대 임포트를 사용해야 합니다.

  • 클래스를 포함하는 모듈에서 클래스를 임포트할 때, 보통 다음과 같이 작성해도 괜찮습니다:
    from myclass import MyClass
    from foo.bar.yourclass import YourClass
    

    이러한 작성 방식이 로컬 이름 충돌을 일으킨다면, 명시적으로 작성하십시오:

    import myclass
    import foo.bar.yourclass
    

    그리고 myclass.MyClassfoo.bar.yourclass.YourClass를 사용하십시오.

  • 와일드카드 임포트(from <module> import *)는 네임스페이스에 어떤 이름이 존재하는지 불명확하게 만들어 독자와 여러 자동화 도구 모두를 혼란스럽게 하므로 피해야 합니다. 와일드카드 임포트를 정당화할 수 있는 한 가지 사용 사례는 내부 인터페이스를 공개 API의 일부로 재공개하는 것입니다(예를 들어, 인터페이스의 순수 파이썬 구현을 선택적 가속화 모듈의 정의로 덮어쓰되, 정확히 어떤 정의가 덮어써질지 미리 알 수 없는 경우).

    이러한 방식으로 이름을 재공개할 때도, 공개 및 내부 인터페이스에 관한 아래 지침이 여전히 적용됩니다.

모듈 수준 던더 이름

__all__, __author__, __version__ 등과 같은 모듈 수준 “던더”(즉, 앞뒤에 밑줄 두 개가 붙은 이름)는 모듈 독스트링 뒤, 그리고 from __future__ 임포트를 제외한 모든 임포트 문 앞에 배치해야 합니다. 파이썬은 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

문자열 인용 부호

파이썬에서 작은따옴표 문자열과 큰따옴표 문자열은 동일합니다. 이 PEP는 이에 대해 권장 사항을 제시하지 않습니다. 규칙 하나를 정해서 일관되게 지키십시오. 다만 문자열에 작은따옴표나 큰따옴표 문자가 포함된 경우에는, 문자열 안에서 백슬래시를 피하기 위해 다른 쪽 따옴표를 사용하십시오. 이는 가독성을 향상시킵니다.

삼중 따옴표 문자열의 경우, PEP 257의 독스트링 규칙과 일관성을 유지하기 위해 항상 큰따옴표 문자를 사용하십시오.

표현식과 문장에서의 공백

사소한 성가심

다음과 같은 상황에서는 불필요한 공백을 피하십시오:

  • 괄호, 대괄호, 중괄호 바로 안쪽:
    # Correct:
    spam(ham[1], {eggs: 2})
    
    # Wrong:
    spam( ham[ 1 ], { eggs: 2 } )
    
  • 후행 쉼표와 그 뒤에 오는 닫는 괄호 사이:
    # Correct:
    foo = (0,)
    
    # Wrong:
    bar = (0, )
    
  • 쉼표, 세미콜론, 콜론 바로 앞:
    # Correct:
    if x == 4: print(x, y); x, y = y, x
    
    # Wrong:
    if x == 4 : print(x , y) ; x , y = y , x
    
  • 다만 슬라이스에서 콜론은 이항 연산자처럼 동작하므로, (가장 낮은 우선순위를 가진 연산자로 취급하여) 양쪽에 동일한 양의 공백을 두어야 합니다. 확장 슬라이스에서는 두 콜론 모두 동일한 양의 공백이 적용되어야 합니다. 예외: 슬라이스 매개변수가 생략된 경우에는 공백도 생략합니다:
    # Correct:
    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]
    
    # Wrong:
    ham[lower + offset:upper + offset]
    ham[1: 9], ham[1 :9], ham[1:9 :3]
    ham[lower : : step]
    ham[ : upper]
    
  • 함수 호출의 인자 목록을 시작하는 여는 괄호 바로 앞:
    # Correct:
    spam(1)
    
    # Wrong:
    spam (1)
    
  • 인덱싱이나 슬라이싱을 시작하는 여는 괄호 바로 앞:
    # Correct:
    dct['key'] = lst[index]
    
    # Wrong:
    dct ['key'] = lst [index]
    
  • 다른 것과 정렬하기 위해 할당(또는 다른) 연산자 주위에 두 개 이상의 공백을 사용하는 경우:
    # Correct:
    x = 1
    y = 2
    long_variable = 3
    
    # Wrong:
    x             = 1
    y             = 2
    long_variable = 3
    

그 밖의 권장 사항

  • 어디에서든 후행 공백을 피하십시오. 후행 공백은 보통 눈에 보이지 않기 때문에 혼란을 줄 수 있습니다. 예를 들어 백슬래시 뒤에 공백과 줄바꿈이 오는 경우는 줄 이어짐 표시로 인식되지 않습니다. 일부 편집기는 후행 공백을 보존하지 않으며, 많은 프로젝트(CPython 자체를 포함)에서는 이를 거부하는 pre-commit 훅을 사용하고 있습니다.
  • 다음 이항 연산자들은 항상 양쪽에 공백을 하나씩 두어 감싸십시오: 할당(=), 복합 할당(+=, -= 등), 비교(==, <, >, !=, <=, >=, in, not in, is, is not), 불리언(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)
    
  • 함수 어노테이션은 콜론에 대한 일반 규칙을 따라야 하며, -> 화살표가 있는 경우 항상 그 주위에 공백을 두어야 합니다. (함수 어노테이션에 대한 자세한 내용은 아래 Function Annotations를 참고하십시오.):
    # Correct:
    def munge(input: AnyStr): ...
    def munge() -> PosInt: ...
    
    # Wrong:
    def munge(input:AnyStr): ...
    def munge()->PosInt: ...
    
  • 키워드 인자를 나타낼 때나 어노테이션이 없는 함수 매개변수의 기본값을 나타낼 때 = 기호 주위에 공백을 사용하지 마십시오:
    # 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)
    

    다만, 인자 어노테이션과 기본값을 함께 사용하는 경우에는 = 기호 주위에 공백을 사용하십시오:

    # 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): ...
    
  • 복합문(한 줄에 여러 문장을 쓰는 것)은 일반적으로 권장되지 않습니다:
    # Correct:
    if foo == 'blah':
        do_blah_thing()
    do_one()
    do_two()
    do_three()
    

    권장하지 않는 예:

    # Wrong:
    if foo == 'blah': do_blah_thing()
    do_one(); do_two(); do_three()
    
  • 본문이 짧은 if/for/while을 같은 줄에 쓰는 것이 괜찮은 경우도 있지만, 절이 여러 개인 문장에는 절대 이렇게 하지 마십시오. 또한 그런 긴 줄을 접어서 쓰는 것도 피하십시오!

    이렇게 하지 않는 편이 좋습니다:

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

    절대 이렇게 하지 마십시오:

    # 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()
    

후행 쉼표를 사용해야 할 때

후행 쉼표는 보통 선택 사항이지만, 요소가 하나뿐인 튜플을 만들 때는 필수입니다. 명확성을 위해서는 후자를 (기술적으로는 불필요한) 괄호로 감싸는 것이 권장됩니다:

# Correct:
FILES = ('setup.cfg',)
# Wrong:
FILES = 'setup.cfg',

후행 쉼표가 불필요한 경우라도, 버전 관리 시스템을 사용할 때, 값·인자·임포트된 항목의 목록이 시간이 지나면서 확장될 것으로 예상될 때는 흔히 도움이 됩니다. 이때의 패턴은 각 값(등)을 한 줄에 하나씩 배치하면서 항상 후행 쉼표를 추가하고, 닫는 괄호/대괄호/중괄호는 다음 줄에 두는 것입니다. 다만 (위에서 언급한 싱글턴 튜플의 경우를 제외하고는) 닫는 구분자와 같은 줄에 후행 쉼표를 두는 것은 의미가 없습니다:

# Correct:
FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           )
# Wrong:
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)

주석

코드와 모순되는 주석은 아예 없는 것보다 더 나쁩니다. 코드가 변경될 때는 항상 주석을 최신 상태로 유지하는 것을 우선순위로 삼으십시오!

주석은 완전한 문장이어야 합니다. 첫 단어는 대문자로 시작해야 하지만, 소문자로 시작하는 식별자인 경우는 예외입니다(식별자의 대소문자는 절대 바꾸지 마십시오!).

블록 주석은 일반적으로 완전한 문장들로 이루어진 하나 이상의 단락으로 구성되며, 각 문장은 마침표로 끝납니다.

여러 문장으로 이루어진 주석에서는 마지막 문장을 제외하고, 문장을 끝맺는 마침표 뒤에 한두 개의 공백을 사용해야 합니다.

여러분이 작성하는 언어를 구사하는 다른 사람들이 주석을 명확하고 쉽게 이해할 수 있도록 하십시오.

영어를 사용하지 않는 국가 출신의 Python 코더 여러분: 코드가 여러분의 언어를 모르는 사람들에게 절대 읽히지 않을 것이라고 120% 확신하지 않는 한, 주석은 영어로 작성하십시오.

블록 주석

블록 주석은 일반적으로 그 뒤에 오는 일부(또는 전체) 코드에 적용되며, 해당 코드와 같은 수준으로 들여씁니다. 블록 주석의 각 줄은 #와 공백 하나로 시작합니다(단, 주석 내부에 들여쓰기된 텍스트인 경우는 제외합니다).

블록 주석 내부의 단락은 # 하나만 포함된 줄로 구분합니다.

인라인 주석

인라인 주석은 아껴서 사용하십시오.

인라인 주석은 문(statement)과 같은 줄에 있는 주석입니다. 인라인 주석은 문과 최소 두 칸의 공백으로 구분되어야 합니다. 인라인 주석은 #과 공백 하나로 시작해야 합니다.

인라인 주석은 당연한 내용을 언급하는 경우 불필요할 뿐만 아니라 사실 주의를 산만하게 만듭니다. 이렇게 하지 마십시오:

x = x + 1                 # Increment x

하지만 때로는 이것이 유용합니다:

x = x + 1                 # Compensate for border

문서화 문자열

좋은 문서화 문자열(“docstring”)을 작성하기 위한 관례는 PEP 257에 불멸의 기록으로 남아 있습니다.

  • 모든 공개 모듈, 함수, 클래스, 메서드에 대해 독스트링을 작성하십시오. 비공개 메서드에는 독스트링이 필요하지 않지만, 해당 메서드가 하는 일을 설명하는 주석은 있어야 합니다. 이 주석은 def 줄 다음에 나와야 합니다.
  • PEP 257은 좋은 독스트링 관례를 설명합니다. 가장 중요한 점은, 여러 줄 독스트링을 끝내는 """는 단독으로 한 줄에 있어야 한다는 것입니다:
    """Return a foobang
    
    Optional plotz says to frobnicate the bizbaz first.
    """
    
  • 한 줄짜리 독스트링의 경우, 닫는 """는 같은 줄에 두십시오:
    """Return an ex-parrot."""
    

이름 규칙

Python 라이브러리의 이름 규칙은 다소 뒤죽박죽이어서 완전히 일관되게 만들 수는 없겠지만, 그럼에도 현재 권장되는 명명 표준은 다음과 같습니다. 새로운 모듈과 패키지(서드파티 프레임워크 포함)는 이 표준에 맞춰 작성해야 하지만, 기존 라이브러리가 다른 스타일을 사용하는 경우에는 내부 일관성을 우선해야 합니다.

최우선 원칙

API의 공개 부분으로서 사용자에게 노출되는 이름은 구현보다 용법을 반영하는 관례를 따라야 합니다.

설명: 명명 스타일

명명 스타일에는 다양한 종류가 있습니다. 어떤 명명 스타일이 사용되고 있는지를, 그것이 어디에 쓰이는지와 무관하게 알아볼 수 있으면 도움이 됩니다.

다음과 같은 명명 스타일들이 흔히 구분됩니다:

  • b (소문자 한 글자)
  • B (대문자 한 글자)
  • lowercase
  • lower_case_with_underscores
  • UPPERCASE
  • UPPER_CASE_WITH_UNDERSCORES
  • CapitalizedWords (또는 CapWords나 CamelCase라고도 하며, 글자 모양이 울퉁불퉁해서 이런 이름이 붙었습니다 [4]). 이는 때때로 StudlyCaps라고도 불립니다.

    참고: CapWords에서 두문자어를 사용할 때는 두문자어의 모든 글자를 대문자로 씁니다. 따라서 HttpServerError보다 HTTPServerError가 더 낫습니다.

  • mixedCase (첫 글자가 소문자라는 점에서 CapitalizedWords와 다릅니다!)
  • Capitalized_Words_With_Underscores (보기 흉합니다!)

관련된 이름들을 묶기 위해 짧고 고유한 접두사를 사용하는 방식도 있습니다. 이 방식은 Python에서는 그다지 사용되지 않지만, 완전성을 위해 언급합니다. 예를 들어, os.stat() 함수는 관례적으로 st_mode, st_size, st_mtime 등과 같은 이름을 가진 항목들로 이루어진 튜플을 반환합니다. (이는 POSIX 시스템 호출 구조체의 필드와의 대응 관계를 강조하기 위한 것으로, 그 구조체에 익숙한 프로그래머에게 도움이 됩니다.)

X11 라이브러리는 모든 공개 함수에 접두사로 X를 붙입니다. Python에서는 속성과 메서드 이름 앞에 객체가 붙고 함수 이름 앞에 모듈 이름이 붙기 때문에, 이 방식이 일반적으로 불필요하다고 여겨집니다.

또한, 앞이나 뒤에 밑줄이 붙는 다음과 같은 특수 형태들도 인식됩니다(이들은 일반적으로 어떤 대소문자 규칙과도 결합될 수 있습니다).

  • _single_leading_underscore: 약한 “내부용” 표시입니다. 예를 들어, from M import *는 이름이 밑줄로 시작하는 객체를 임포트하지 않습니다.
  • single_trailing_underscore_: 관례적으로 Python 키워드와의 충돌을 피하기 위해 사용됩니다. 예:
    tkinter.Toplevel(master, class_='ClassName')
    
  • __double_leading_underscore: 클래스 속성 이름을 지을 때, 이름 맹글링(name mangling)을 유발합니다(class FooBar 내부에서 __boo_FooBar__boo가 됩니다; 아래를 참조하십시오).
  • __double_leading_and_trailing_underscore__: 사용자가 제어하는 네임스페이스에 존재하는 “매직” 객체나 속성입니다. 예: __init__, __import__, __file__ 등입니다. 이러한 이름을 임의로 만들어내지 마십시오. 문서화된 대로만 사용하십시오.

규범적 지침: 이름 짓기 규칙

피해야 할 이름

‘l’(소문자 엘), ‘O’(대문자 오), ‘I’(대문자 아이) 문자를 한 글자짜리 변수 이름으로 절대 사용하지 마십시오.

일부 글꼴에서는 이 문자들이 숫자 1과 0과 구별되지 않습니다. ‘l’을 사용하고 싶은 유혹이 들 때는 대신 ‘L’을 사용하십시오.

ASCII 호환성

표준 라이브러리에서 사용되는 식별자는 PEP 3131정책 절에서 설명된 대로 ASCII와 호환되어야 합니다.

패키지와 모듈 이름

모듈은 짧고 모두 소문자인 이름을 가져야 합니다. 가독성이 향상된다면 모듈 이름에 밑줄을 사용할 수 있습니다. Python 패키지 역시 짧고 모두 소문자인 이름을 가져야 하지만, 밑줄 사용은 권장되지 않습니다.

C나 C++로 작성된 확장 모듈에 더 상위 수준(예: 더 객체 지향적인) 인터페이스를 제공하는 Python 모듈이 딸려 있는 경우, C/C++ 모듈 이름 앞에는 밑줄을 붙입니다(예: _socket).

클래스 이름

클래스 이름은 일반적으로 CapWords 관례를 사용해야 합니다.

인터페이스가 문서화되어 있고 주로 호출 가능 객체로 사용되는 경우에는 함수용 명명 관례를 대신 사용할 수 있습니다.

내장 이름에는 별도의 관례가 있다는 점에 유의하십시오: 대부분의 내장 이름은 단일 단어(또는 두 단어를 붙인 것)이며, CapWords 관례는 예외 이름과 내장 상수에만 사용됩니다.

타입 변수 이름

타입 변수의 이름은 PEP 484에서 도입되었으며, 일반적으로 짧은 이름을 선호하는 CapWords 규칙을 사용합니다(T, AnyStr, Num). 공변(covariant) 또는 반변(contravariant) 동작을 선언하는 데 사용되는 변수에는 각각 _co 또는 _contra 접미사를 추가하는 것이 권장됩니다:

from typing import TypeVar

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

예외 이름

예외는 클래스여야 하므로, 여기에도 클래스 명명 관례가 적용됩니다. 다만 예외 이름에는 “Error” 접미사를 사용해야 합니다(해당 예외가 실제로 오류인 경우).

전역 변수 이름

(이러한 변수들은 한 모듈 내부에서만 사용되도록 의도된 것이기를 바랍시다.) 관례는 함수의 경우와 거의 동일합니다.

from M import *를 통해 사용하도록 설계된 모듈은 __all__ 메커니즘을 사용하여 전역 변수를 내보내지 않도록 하거나, 이러한 전역 변수 앞에 밑줄을 붙이는 오래된 관례를 사용해야 합니다(이는 해당 전역 변수가 “모듈 비공개”임을 나타내기 위해 사용할 수 있습니다).

함수와 변수 이름

함수 이름은 소문자로 작성하며, 가독성을 높이기 위해 필요에 따라 단어 사이를 밑줄로 구분합니다.

변수 이름은 함수 이름과 같은 관례를 따릅니다.

mixedCase는 하위 호환성을 유지하기 위해 이미 그러한 스타일이 지배적인 경우(예: threading.py)에만 허용됩니다.

함수와 메서드 인자

인스턴스 메서드의 첫 번째 인자에는 항상 self를 사용하십시오.

클래스 메서드의 첫 번째 인자에는 항상 cls를 사용하십시오.

함수 인자의 이름이 예약어와 충돌하는 경우, 약어를 사용하거나 철자를 변형하는 것보다 끝에 밑줄 하나를 붙이는 것이 일반적으로 더 좋습니다. 따라서 clss보다는 class_가 더 좋습니다. (아마 더 좋은 방법은 동의어를 사용하여 이러한 충돌을 피하는 것입니다.)

메서드 이름과 인스턴스 변수

함수 이름 규칙을 사용합니다: 가독성을 높이기 위해 필요에 따라 단어 사이를 밑줄로 구분한 소문자를 사용합니다.

비공개 메서드와 인스턴스 변수에만 밑줄 하나를 앞에 붙여 사용하십시오.

서브클래스와의 이름 충돌을 피하기 위해, 파이썬의 이름 맹글링(name mangling) 규칙을 적용하려면 밑줄 두 개를 앞에 붙이십시오.

파이썬은 클래스 이름을 사용하여 이러한 이름을 맹글링합니다. 즉, 클래스 Foo에 __a라는 속성이 있으면 Foo.__a로는 접근할 수 없습니다. (끈질긴 사용자라면 Foo._Foo__a를 호출하여 여전히 접근할 수 있습니다.) 일반적으로, 앞에 밑줄 두 개를 붙이는 것은 서브클래싱을 위해 설계된 클래스의 속성과 이름이 충돌하는 것을 피하기 위해서만 사용해야 합니다.

참고: __names의 사용에 대해서는 다소 논란이 있습니다(아래 참조).

상수

상수는 보통 모듈 수준에서 정의되며, 단어 사이를 밑줄로 구분한 모두 대문자로 작성합니다. 예로는 MAX_OVERFLOWTOTAL이 있습니다.

상속을 위한 설계

클래스의 메서드와 인스턴스 변수(통칭하여 “속성”)를 공개로 할지 비공개로 할지는 항상 결정해야 합니다. 확신이 서지 않는다면 비공개를 선택하십시오. 나중에 공개로 바꾸는 것이 공개 속성을 비공개로 바꾸는 것보다 쉽습니다.

공개 속성은 여러분의 클래스와 관련 없는 클라이언트가 사용할 것으로 예상하는 것이며, 하위 호환성을 깨는 변경을 피하겠다는 약속이 수반됩니다. 비공개 속성은 제3자가 사용하도록 의도되지 않은 것으로, 비공개 속성이 변경되거나 심지어 제거되지 않는다는 보장은 하지 않습니다.

파이썬에서는 (일반적으로 불필요한 정도의 작업 없이는) 어떤 속성도 진정으로 비공개(“private”)가 아니므로, 여기서는 “private”이라는 용어를 사용하지 않습니다.

속성의 또 다른 범주로는 “서브클래스 API”(다른 언어에서는 흔히 “protected”라고 불림)의 일부인 것들이 있습니다. 일부 클래스는 클래스의 동작 측면을 확장하거나 수정하기 위해 상속받도록 설계됩니다. 이러한 클래스를 설계할 때는 어떤 속성이 공개인지, 어떤 속성이 서브클래스 API의 일부인지, 그리고 어떤 속성이 정말로 베이스 클래스만 사용해야 하는지를 명시적으로 결정하도록 주의를 기울이십시오.

이를 염두에 두고, 파이썬다운 지침은 다음과 같습니다:

  • 공개 속성에는 앞에 밑줄을 붙이지 않아야 합니다.
  • 공개 속성 이름이 예약어와 충돌하는 경우, 속성 이름 끝에 밑줄 하나를 추가하십시오. 이는 축약형이나 철자를 뭉갠 표기보다 바람직합니다. (그러나 이 규칙에도 불구하고, 클래스임이 알려진 변수나 인자, 특히 클래스 메서드의 첫 번째 인자에는 ‘cls’라는 표기가 선호됩니다.)

    참고 1: 클래스 메서드에 대한 위의 인자 이름 권장 사항을 참조하십시오.

  • 단순한 공개 데이터 속성의 경우, 복잡한 접근자/변경자 메서드 없이 속성 이름만 노출하는 것이 가장 좋습니다. 단순한 데이터 속성이 기능적 동작으로 발전해야 할 필요가 생기더라도, 파이썬은 미래의 개선을 위한 쉬운 경로를 제공한다는 점을 유념하십시오. 그런 경우에는 프로퍼티를 사용하여 기능적 구현을 단순한 데이터 속성 접근 구문 뒤에 숨기십시오.

    참고 1: 캐싱과 같은 부작용은 일반적으로 괜찮지만, 기능적 동작은 가급적 부작용이 없도록 유지하십시오.

    참고 2: 계산 비용이 많이 드는 연산에는 프로퍼티 사용을 피하십시오. 속성 표기법은 호출자로 하여금 접근 비용이 (상대적으로) 저렴하다고 믿게 만듭니다.

  • 클래스가 서브클래스화될 것을 의도하고 있고, 서브클래스가 사용하지 않기를 바라는 속성이 있다면, 앞에 밑줄 두 개를 붙이고 뒤에는 밑줄을 붙이지 않는 이름 규칙을 고려하십시오. 이는 파이썬의 이름 맹글링 알고리즘을 발동시키며, 이 알고리즘은 클래스 이름을 속성 이름에 뒤섞어 넣습니다. 이는 서브클래스가 실수로 같은 이름의 속성을 갖게 되더라도 속성 이름 충돌을 피하는 데 도움이 됩니다.

    참고 1: 맹글링된 이름에는 단순한 클래스 이름만 사용되므로, 서브클래스가 같은 클래스 이름과 속성 이름을 모두 선택하면 여전히 이름 충돌이 발생할 수 있다는 점에 유의하십시오.

    참고 2: 이름 맹글링은 디버깅이나 __getattr__()과 같은 특정 용도를 덜 편리하게 만들 수 있습니다. 그러나 이름 맹글링 알고리즘은 문서화가 잘 되어 있어 수동으로 수행하기도 쉽습니다.

    참고 3: 모든 사람이 이름 맹글링을 좋아하는 것은 아닙니다. 우발적인 이름 충돌을 피해야 할 필요성과 고급 호출자에 의한 잠재적 사용 사이의 균형을 맞추도록 노력하십시오.

공개 인터페이스와 내부 인터페이스

하위 호환성 보장은 오직 공개 인터페이스에만 적용됩니다. 따라서 사용자가 공개 인터페이스와 내부 인터페이스를 명확히 구분할 수 있는 것이 중요합니다.

문서화가 명시적으로 잠정적이거나 통상적인 하위 호환성 보장에서 제외되는 내부 인터페이스라고 선언하지 않는 한, 문서화된 인터페이스는 공개된 것으로 간주됩니다. 문서화되지 않은 모든 인터페이스는 내부 인터페이스로 간주해야 합니다.

인트로스펙션을 더 잘 지원하기 위해, 모듈은 __all__ 속성을 사용하여 공개 API의 이름을 명시적으로 선언해야 합니다. __all__을 빈 리스트로 설정하면 해당 모듈에 공개 API가 없음을 나타냅니다.

__all__을 적절히 설정했더라도, 내부 인터페이스(패키지, 모듈, 클래스, 함수, 속성 또는 기타 이름)는 여전히 앞에 밑줄 하나를 붙여야 합니다.

이를 포함하는 네임스페이스(패키지, 모듈 또는 클래스)가 내부적인 것으로 간주된다면, 해당 인터페이스 또한 내부적인 것으로 간주됩니다.

임포트된 이름은 항상 구현 세부 사항으로 간주해야 합니다. 다른 모듈은 os.path나 하위 모듈의 기능을 노출하는 패키지의 __init__ 모듈처럼 포함 모듈의 API 중 명시적으로 문서화된 부분이 아닌 한, 이렇게 임포트된 이름에 대한 간접 접근에 의존해서는 안 됩니다.

프로그래밍 권장 사항

  • 코드는 파이썬의 다른 구현(PyPy, Jython, IronPython, Cython, Psyco 등)에 불리하지 않은 방식으로 작성해야 합니다.

    예를 들어, a += ba = a + b 형태의 문에 대해 CPython의 효율적인 제자리 문자열 연결 구현에 의존하지 마십시오. 이 최적화는 CPython에서조차 취약하며(일부 타입에서만 동작합니다), 참조 카운팅을 사용하지 않는 구현에서는 전혀 존재하지 않습니다. 라이브러리의 성능에 민감한 부분에서는 대신 ''.join() 형태를 사용해야 합니다. 이렇게 하면 다양한 구현 전반에서 연결이 선형 시간에 이루어지도록 보장할 수 있습니다.

  • None과 같은 싱글턴과의 비교는 항상 isis not을 사용해야 하며, 동등 연산자를 사용해서는 안 됩니다.

    또한, 실제로는 if x is not None을 의미할 때 if x라고 쓰지 않도록 주의하십시오 – 예를 들어 기본값이 None인 변수나 인자가 다른 값으로 설정되었는지 검사할 때가 그렇습니다. 그 다른 값은 불리언 컨텍스트에서 거짓으로 평가될 수 있는 타입(예: 컨테이너)을 가질 수도 있습니다!

  • not ... is보다는 is not 연산자를 사용하십시오. 두 표현식은 기능적으로 동일하지만, 전자가 더 읽기 쉬우며 선호됩니다:
    # Correct:
    if foo is not None:
    
    # Wrong:
    if not foo is None:
    
  • 리치 비교로 순서 연산을 구현할 때는, 다른 코드가 특정 비교만 사용할 것이라고 가정하기보다는 여섯 가지 연산(__eq__, __ne__, __lt__, __le__, __gt__, __ge__) 모두를 구현하는 것이 가장 좋습니다.

    이에 드는 노력을 최소화하기 위해, functools.total_ordering() 데코레이터는 누락된 비교 메서드를 생성하는 도구를 제공합니다.

    PEP 207은 반사성 규칙이 Python에서 실제로 가정된다는 것을 나타냅니다. 따라서 인터프리터는 y > xx < y로, y >= xx <= y로 바꿀 수 있으며, x == yx != y의 인자를 서로 바꿀 수도 있습니다. sort()min() 연산은 < 연산자를 사용한다고 보장되며, max() 함수는 > 연산자를 사용합니다. 그러나 다른 맥락에서 혼란이 생기지 않도록 여섯 가지 연산 모두를 구현하는 것이 가장 좋습니다.

  • 람다 표현식을 식별자에 직접 바인딩하는 할당문 대신 항상 def 문을 사용하십시오:
    # Correct:
    def f(x): return 2*x
    
    # Wrong:
    f = lambda x: 2*x
    

    첫 번째 형태는 결과로 생성되는 함수 객체의 이름이 일반적인 ‘<lambda>’ 대신 구체적으로 ‘f’가 된다는 것을 의미합니다. 이는 일반적으로 트레이스백과 문자열 표현에 더 유용합니다. 할당문을 사용하면 람다 표현식이 명시적인 def 문에 비해 제공할 수 있는 유일한 이점(즉, 더 큰 표현식 안에 내장될 수 있다는 점)이 사라집니다.

  • 예외는 BaseException이 아니라 Exception에서 파생시키십시오. BaseException을 직접 상속하는 것은 그것을 잡는 것이 거의 항상 잘못된 경우인 예외를 위해 예약되어 있습니다.

    예외 계층 구조는 예외가 발생하는 위치가 아니라, 예외를 잡는 코드가 필요로 할 가능성이 높은 구분에 기반하여 설계하십시오. “문제가 발생했다”고만 말하기보다는 “무엇이 잘못되었는가”라는 질문에 프로그램적으로 답하는 것을 목표로 하십시오(내장 예외 계층 구조에서 이 교훈이 어떻게 적용되었는지에 대한 예는 PEP 3151을 참고하십시오).

    여기서도 클래스 명명 규칙이 적용되지만, 예외가 오류인 경우 예외 클래스에 “Error” 접미사를 추가해야 합니다. 비지역적 흐름 제어나 다른 형태의 신호 전달에 사용되는 비오류성 예외는 특별한 접미사가 필요하지 않습니다.

  • 예외 체이닝을 적절히 사용하십시오. raise X from Y는 원래의 트레이스백을 잃지 않으면서 명시적인 대체를 나타내는 데 사용해야 합니다.

    내부 예외를 의도적으로 교체할 때(raise X from None을 사용하여)는, 관련된 세부 정보가 새 예외로 전달되도록 하십시오(예를 들어 KeyError를 AttributeError로 변환할 때 속성 이름을 보존하거나, 원래 예외의 텍스트를 새 예외 메시지에 포함시키는 것).

  • 예외를 잡을 때는, 맨 except: 절을 사용하는 대신 가능한 한 구체적인 예외를 명시하십시오:
    try:
        import platform_specific_module
    except ImportError:
        platform_specific_module = None
    

    except: 절은 SystemExit과 KeyboardInterrupt 예외까지 잡아버려서, Control-C로 프로그램을 중단하기 어렵게 만들고, 다른 문제를 숨길 수 있습니다. 프로그램 오류를 나타내는 모든 예외를 잡고 싶다면 except Exception:을 사용하십시오(맨 except는 except BaseException:과 동등합니다).

    맨 ‘except’ 절의 사용을 다음 두 가지 경우로 제한하는 것이 좋은 경험칙입니다:

    1. 예외 처리기가 트레이스백을 출력하거나 로깅할 경우; 적어도 사용자는 오류가 발생했다는 것을 알게 됩니다.
    2. 코드가 어떤 정리 작업을 해야 하지만, 그 후 raise로 예외를 위쪽으로 전파시키는 경우. 이 경우에는 try...finally가 더 나은 처리 방법일 수 있습니다.
  • 운영 체제 오류를 잡을 때는, errno 값을 조사하는 것보다 Python 3.3에서 도입된 명시적인 예외 계층 구조를 선호하십시오.
  • 또한, 모든 try/except 절에서는 try 절을 반드시 필요한 최소한의 코드로 제한하십시오. 이 역시 버그를 숨기는 것을 방지합니다.
    # Correct:
    try:
        value = collection[key]
    except KeyError:
        return key_not_found(key)
    else:
        return handle_value(value)
    
    # Wrong:
    try:
        # Too broad!
        return handle_value(collection[key])
    except KeyError:
        # Will also catch KeyError raised by handle_value()
        return key_not_found(key)
    
  • 자원이 특정 코드 영역에 국한된 경우, 사용 후 신속하고 확실하게 정리되도록 with 문을 사용하십시오. try/finally 문도 허용됩니다.
  • 컨텍스트 관리자는 자원의 획득과 해제 외의 작업을 수행하는 경우, 별도의 함수나 메서드를 통해 호출되어야 합니다.
    # Correct:
    with conn.begin_transaction():
        do_stuff_in_transaction(conn)
    
    # Wrong:
    with conn:
        do_stuff_in_transaction(conn)
    

    후자의 예시는 __enter____exit__ 메서드가 트랜잭션 후 연결을 닫는 것 외의 다른 작업을 수행하고 있음을 나타내는 정보를 전혀 제공하지 않습니다. 이런 경우에는 명시적으로 작성하는 것이 중요합니다.

  • return 문은 일관성 있게 작성하십시오. 함수 내의 모든 return 문은 표현식을 반환하거나, 아니면 어느 것도 반환하지 않아야 합니다. 어떤 return 문이 표현식을 반환한다면, 값을 반환하지 않는 return 문은 return None이라고 명시적으로 작성해야 하며, (도달 가능한 경우) 함수 끝에는 명시적인 return 문이 있어야 합니다.
    # Correct:
    
    def foo(x):
        if x >= 0:
            return math.sqrt(x)
        else:
            return None
    
    def bar(x):
        if x < 0:
            return None
        return math.sqrt(x)
    
    # Wrong:
    
    def foo(x):
        if x >= 0:
            return math.sqrt(x)
    
    def bar(x):
        if x < 0:
            return
        return math.sqrt(x)
    
  • 접두사나 접미사를 확인할 때는 문자열 슬라이싱 대신 ''.startswith()''.endswith()를 사용하십시오.

    startswith()와 endswith()는 더 깔끔하고 오류가 적습니다.

    # Correct:
    if foo.startswith('bar'):
    
    # Wrong:
    if foo[:3] == 'bar':
    
  • 객체 타입 비교는 타입을 직접 비교하는 대신 항상 isinstance()를 사용해야 합니다.
    # Correct:
    if isinstance(obj, int):
    
    # Wrong:
    if type(obj) is type(1):
    
  • 시퀀스(문자열, 리스트, 튜플)의 경우, 빈 시퀀스는 거짓이라는 사실을 활용하십시오.
    # Correct:
    if not seq:
    if seq:
    
    # Wrong:
    if len(seq):
    if not len(seq):
    
  • 의미 있는 후행 공백에 의존하는 문자열 리터럴을 작성하지 마십시오. 그러한 후행 공백은 시각적으로 구분할 수 없으며, 일부 편집기(또는 더 최근에는 reindent.py)가 이를 잘라낼 수도 있습니다.
  • 불리언 값을 ==를 사용하여 True나 False와 비교하지 마십시오:
    # Correct:
    if greeting:
    
    # Wrong:
    if greeting == True:
    

    더 나쁜 예:

    # Wrong:
    if greeting is True:
    
  • try...finally의 finally 절 안에서 흐름 제어문 return/break/continue를 사용하여 흐름 제어문이 finally 절 밖으로 빠져나가게 하는 것은 권장되지 않습니다. 이는 그러한 문장이 finally 절을 통해 전파되는 활성 예외를 암묵적으로 취소하기 때문입니다:
    # Wrong:
    def foo():
        try:
            1 / 0
        finally:
            return 42
    

함수 어노테이션

함수 어노테이션의 스타일 규칙은 PEP 484가 채택됨에 따라 변경되었습니다.

  • 함수 어노테이션은 PEP 484 구문을 사용해야 합니다(이전 절에 어노테이션에 대한 형식 권장 사항이 있습니다).
  • 이 PEP에서 이전에 권장되었던 어노테이션 스타일 실험은 더 이상 권장되지 않습니다.
  • 그러나 표준 라이브러리 외부에서는 PEP 484의 규칙 내에서의 실험이 이제 권장됩니다. 예를 들어, 대규모 서드파티 라이브러리나 애플리케이션에 PEP 484 스타일의 타입 어노테이션을 표시하고, 그 어노테이션을 추가하는 것이 얼마나 쉬웠는지 검토하며, 그 존재가 코드 이해도를 높이는지 관찰하는 것입니다.
  • 파이썬 표준 라이브러리는 이러한 어노테이션을 채택하는 데 보수적이어야 하지만, 새 코드와 대규모 리팩터링에는 그 사용이 허용됩니다.
  • 함수 어노테이션을 다른 용도로 사용하고자 하는 코드에는 다음 형식의 주석을 넣는 것이 권장됩니다:
    # type: ignore
    

    파일 상단 근처에; 이는 타입 검사기에게 모든 어노테이션을 무시하도록 지시합니다. (타입 검사기의 경고를 비활성화하는 더 세밀한 방법은 PEP 484에서 찾을 수 있습니다.)

  • 린터와 마찬가지로, 타입 검사기는 선택적이고 별도인 도구입니다. 파이썬 인터프리터는 기본적으로 타입 검사로 인해 어떤 메시지도 발생시키지 않아야 하며, 어노테이션에 기반하여 동작을 바꾸지 않아야 합니다.
  • 타입 검사기를 사용하고 싶지 않은 사용자는 이를 무시해도 됩니다. 하지만 서드파티 라이브러리 패키지 사용자는 해당 패키지에 대해 타입 검사기를 실행하고 싶어할 수 있다고 예상됩니다. 이러한 목적을 위해 PEP 484는 스텁 파일, 즉 해당하는 .py 파일보다 우선하여 타입 검사기가 읽는 .pyi 파일의 사용을 권장합니다. 스텁 파일은 라이브러리와 함께 배포되거나, (라이브러리 작성자의 허락을 받아) typeshed 저장소 [5]를 통해 별도로 배포될 수 있습니다.

변수 어노테이션

PEP 526은 변수 어노테이션을 도입했습니다. 이에 대한 스타일 권장 사항은 위에서 설명한 함수 어노테이션에 대한 것과 유사합니다.

  • 모듈 수준 변수, 클래스 및 인스턴스 변수, 지역 변수에 대한 어노테이션은 콜론 뒤에 공백을 하나만 두어야 합니다.
  • 콜론 앞에는 공백이 없어야 합니다.
  • 대입문에 오른쪽 값이 있는 경우, 등호는 양쪽에 정확히 공백을 하나씩 두어야 합니다:
    # Correct:
    
    code: int
    
    class Point:
        coords: Tuple[int, int]
        label: str = '<unknown>'
    
    # Wrong:
    
    code:int  # No space after colon
    code : int  # Space before colon
    
    class Test:
        result: int=0  # No spaces around equality sign
    
  • Python 3.6에서 PEP 526이 승인되었지만, 변수 어노테이션 구문은 모든 버전의 Python에서 스텁 파일에 선호되는 구문입니다(자세한 내용은 PEP 484를 참조하십시오).

각주

참고 자료