# 코드 레이아웃
# 들여쓰기
각 들여쓰기 레벨마다 4칸 공백을 사용하자.
여러 줄에 이어지는 문장에서는 괄호 안의 Python의 암시적 줄 결합을 사용하여 괄호들로 감싸진 요소들의 세로줄을 맞추어야 한다. 또는 내어쓰기[1]를 사용하여 세로줄을 맞추어야 한다. 내어쓰기를 사용할 때는 고려해야 할 사항이 있다. 우선, 첫 번째 줄에는 아규먼트가 없어야한다. 그리고 추가적인 들여쓰기는 여러 줄에 이어지는 문장 자체를 구분하는 데에 사용되어야 한다.
# 옳은 예:
# 열린 구분 문자(역: 여기서는 소괄호)를 기준으로 정렬된다.
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)
# 내어쓰기는 레벨을 더해야 한다. (역: 나머지 줄에 들여쓰기를 해야 한다는 의미)
foo = long_function_name(
var_one, var_two,
var_three, var_four)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 잘못된 예:
# 세로줄을 맞추지 않았을 때, 첫 번째 줄에 아규먼트는 없어야 한다.
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)
2
3
4
5
6
7
8
9
10
11
여러 줄에 이어지는 문장에서 4칸 공백 들여쓰기 규칙은 선택 사항이다.
# 내어쓰기는 4칸 공백 외의 방식으로 들여쓰기가 *될 수도 있다* (역: 여기서는 2칸 공백 규칙이 적용되었다.)
foo = long_function_name(
var_one, var_two,
var_three, var_four)
2
3
4
if
-문의 조건 부분이 길어 여러 줄로 작성 될 필요가 있는 경우를 보자. if
키워드에 한 칸 공백과 열린 소괄호를 붙여 작성하면, 나머지 여러 줄로 작성 된 조건부가 저절로 4칸 공백 들여쓰기 되는 것에 주목해야 한다.
이는 if-문 내 중첩되어 있는 코드 모음과 시각적인 충돌을 일으킬 수 있다. (이 코드 모음도 4칸 공백 들여쓰기가 되어 있을 경우)
이 PEP 문서에서는 if-문 내 중첩되어 있는 문장으로부터 이러한 조건 부분에 대해 시각적으로 어떻게 추가적인 구별을 할 것인지 (또는 구별을 할 것인지 하지 않을 것인지)에 대한 명백한 입장이 없다. 이런 상황에서 혀용 가능한 선택을 제시하되, 제한하지는 않을 것이다.
# 추가적인 들여쓰기를 하지 않은 경우
if (this_is_one_thing and
that_is_another_thing):
do_something()
# 구문 하이라이터(syntax highlighter)를 지원하는 에디터에서
# 구별할 수 있게 주석을 더하기
if (this_is_one_thing and
that_is_another_thing):
# 두 조건들이 참일 때, 뭐라뭐라....
do_something()
# 여러 줄에 이어지는 조건 줄에서 추가적인 들여쓰기를 한 경우
if (this_is_one_thing
and that_is_another_thing):
do_something()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(이항 연산자의 앞뒤로 띄어쓰기를 할 것인지에 대한 논의를 아래의 섹션에서 확인할 수 있다.)
여러 줄 구조에서 닫힌 괄호들은 리스트의 마지막 줄 공백이 아닌 첫 번째 문자를 기준으로 세로줄을 맞출 수 있다.
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
2
3
4
5
6
7
8
또는 시작하는 줄의 첫 번째 문자를 기준으로 세로줄을 맞출 수 있다.
my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
'a', 'b', 'c',
'd', 'e', 'f',
)
2
3
4
5
6
7
8
# 탭 아니면 스페이스?
스페이스가 더 나은 들여쓰기 방식이다.
탭은 이미 탭으로 들여쓰기 된 코드에서 일관성 유지를 위해서만 사용되어야 한다.
Python 3에서는 들여쓰기에 탭과 스페이스를 혼용하는 것을 허용하지 않는다.
탭과 스페이스를 혼용하여 들여쓰기 한 Python 2 코드는 오로지 스페이스만을 사용하는 것으로 바꿔야 한다.
-t
옵션과 함께 Python 2 명령 줄 인터프리터(command line interpreter)를 호출(invoke) 하면 탭과 스페이스가 잘못 혼용된 코드에 대해 경고한다. -tt
옵션을 사용할 때는 경고 대신 에러가 발생한다. 이 옵션들을 매우 권장한다!
# 한 줄의 최대 길이
모든 줄은 한 줄 당 최대 79개의 문자까지 적을 수 있다.
구조적인 제약을 덜 받는, 이어지는 긴 텍스트 블록(독스트링 또는 주석)도 줄 당 72개 문자로 제한되어야 한다.
필요한 에디터 창의 너비를 제한하는 것은 여러 파일들의 창 분할을 가능하게 하고, 인접한 열들에 두 가지 버전으로 보여주는 리뷰 툴을 사용할 때 유용하다.
대부분의 툴들에서의 디폴트 래핑은 코드의 시각적 구조를 방해하여, 이해하는 것을 더 어렵게 한다. 비록 툴이 마지막 열에 글리프 표식(glyph)[2]을 두었더라도, 창 너비를 80으로 설정한 에디터에서 래핑하는 것을 피하도록 하자. 몇 웹 기반 툴들은 다이나믹 라인(dynamic line) 래핑을 전혀 제공하지 않는다.
몇몇 팀은 줄의 길이가 더 긴 것을 아주 선호한다. 이 이슈에 동의하는 팀의 우선적으로 또는 배타적으로 유지되는 코드를 위해, 주석이나 독스트링만은 72자로 여전히 제한되도록 하면서, 줄 당 길이 제한을 99까지 늘리는 것은 허용한다.
Python 표준 라이브러리는 보수적이며, 각 줄을 79자로 제한한다. (그리고 독스트링/주석은 72자까지)
긴 줄을 래핑하는 바람직한 방법은 Python의 괄호 내 암시적 줄 잇기 방식을 사용하는 것이다. 긴 줄들은 여러줄에 걸쳐 괄호로 표현을 래핑하는 하는 것으로 줄 바꿈을 할 수 있다. 여러 줄이 계속해서 이어질 때 백슬래시를 사용하는 방법보다 이러한 방법을 사용하는 것이 바람직하다.
백슬래시가 여전히 적절한 경우가 있다. 예를 들어, 길고 여러 줄인 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())
2
3
(여러 줄 with
-문에서의 들여쓰기 뿐 아니라, 여러 줄의 if
-문에 대한 이전의 논의를 보라.)
또 다른 예시로는 assert
문이 있다.
여러 줄에 걸쳐 이어지는 문장은 적절히 들여쓰기 해야함을 명심하자.
# 이항 연산자 앞뒤로 줄바꿈을 해야할까?
지난 수십 년 간 권장된 스타일은 이항 연산자 이후에 줄 바꿈을 하는 것이다. 하지만 이는 두 가지 이유로 가독성을 해칠 수 있다. 첫째, 연산자들이 화면의 여러 열(columns)에 흩어지는 경향이 있다. 둘째, 각 연산자가 대응되는 피연산자로부터 떨어져 이전 줄로 이동한다. 여기, 어느 피연산자를 더하고 빼는 것인지 알기 위해 우리의 눈이 더 열심히 일해야 하는 예시가 있다.
# 잘못된 예
# 연산자가 대응되는 피연산자로부터 멀리 떨어져 있다.
income = (gross_wages +
taxable_interest +
(dividends - qualified_dividends) -
ira_deduction -
student_loan_interest)
2
3
4
5
6
7
이 가독성 문제를 해결하기 위해, 수학자들과 그들의 퍼블리셔들은 반대의 컨벤션을 다른다. Donald Knuth 는 그의 Computers and Typesetting 시리즈에서 다음의 전통적인 규칙을 설명한다. "비록 단락 내의 공식은 항상 이항 연산 및 관계 뒤에 줄 바꿈을 하지만, 표시된 공식은 항상 이항 연산 전에 줄 바꿈을 한다."[3]
수학으로부터 온 전통을 따르는 것은 대게 더 가독성 있는 코드를 결과로 낸다.
# 옳은 예:
# 연산자와 피연산자를 구별하기 쉽다.
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
2
3
4
5
6
7
Python 코드에선, 컨벤션이 국지적으로 일관성이 있는 한 이항 연산자 앞이나 뒤에 줄 바꿈을 하는 것이 허용된다. 새로운 코드의 경우 Knuth의 스타일이 제안된다.
# 공백 줄
최상위 레벨 함수와 클래스 정의 앞뒤로 두 개의 공백 줄이 감싸진다.
클래스 내의 메소드 정의 앞뒤로는 한 개의 공백 줄이 감싸진다.
관련된 함수들의 모음을 분리하기 위해 추가적인 공백 줄이 (꼭 필요한 경우에만) 사용될 수 있다. 공백 줄은 관련된 one-liner[4] 의 모음 사이에서 생략될 수 있다. (예를 들면, 더미 구현의 집합)
함수 내 공백 줄은 논리적인 섹션을 구분할 때 적절하게 사용하자.
Python 은 컨트롤 + L (^L) 폼 피드(form feed) 문자를 공백으로 받아들인다. 많은 툴들이 이 문자를 페이지 구분자로 취급하므로, 이를 파일 내 서로 관련된 섹션들의 페이지를 분리하기 위해 사용할 수 있다. 단, 몇 에디터와 웹 기반 코드 뷰어에서는 컨트롤 + L 이 폼 피드로 인식되지 않을 수 있다는 점을 주의하자. 그 웹 기반 코드 뷰어는 그 위치에 다른 글리프를 보여줄 것이다.
# 소스 파일 인코딩
코어 Python 배포 코드는 항상 UTF-8을 사용해야 한다. (또는 Python 2 에서는 ASCII)
아스키(Python 2 에서) 또는 UTF-8(Python 3 에서)을 사용하는 파일들은 인코딩 선언부(declaration)를 포함하면 안된다.
표준 라이브러리에서는, 디폴트 값이 아닌 인코딩은 테스트 목적 또는 주석이나 독스트링에서 아스키 문자가 아닌 문자를 포함하는 작성자의 이름을 언급할 때만 사용되어야 한다. 반면에 \x
, \u
, \U
, \N
이스케이프를 사용하는 것은 문자열 리터럴 내에 아스키가 아닌 데이터를 포함하기 위한 바람직한 방법이다.
Python 3.0 과 그 이상은, 다음의 정책이 표준 라이브러리에 의해 규정되어있다. (PEP 3131open in new window 참고) Python 표준 라이브러리 내의 모든 식별자들은 반.드.시. 아스키로만 이루어진 식별자들을 사용해야 하며, 가능한 한 영어를 사용해야한다. (많은 경우에, 약어나 기술적인 용어만을 영어가 아니어도 사용한다.) 덧붙여, 문자열 리터럴과 주석 또한 아스키여야한다. 다음의 경우만 예외인데, (a) 아스키가 아닌 기능을 테스트하는 테스트 케이스 그리고, (b) 라틴 알파벳(latin-1, ISO/IEC 8859-1 character set)에 기반하지 않은 작성자명 일 땐, 반드시 이 문자 집합에서 이름의 전자(transliteration)[5]를 제공해야 한다.
전세계의 사용자를 대상으로 하는 오픈 소스 프로젝트는 유사한 정책을 채택하길 권장한다.
# 가져오기
가져오기(Imports)는 분리된 줄에 사용해야 한다.
# 옳은 예 import os import sys
1
2
3# 잘못된 예 import sys, os
1
2이것도 괜찮다.
# 옳은 예 from subprocess import Popen, PIPE
1
2가져오기는 항상 파일의 맨 위에 놓여져 있다. 세세하게는 모듈 주석과 독스트링 바로 다음에, 모듈 전역과 상수 바로 전에 놓여져 있다.
가져오기는 다음의 순서에 따라 구분되어야 한다.
- 표준 라이브러리 가져오기
- 관련 서드 파티 가져오기
- 로컬 어플리케이션/라이브러리 가져오기
각 가져오기 모음 사이에 공백 줄을 넣어야한다.
절대 경로 가져오기가 권장된다. 대체적으로 이 편이 가독성이 좋다. 가져오기 체계가 잘못 구성 되었을 때도(예를 들어, 패키지 내부의 디렉토리가
sys.path
에서 끝나는 경우), 더 나은 행위를 하는 경향이 있다. (그게 아니더라도, 최소한 더 나은 에러 메시지를 준다.)import mypkg.sibling from mypkg import sibling from mypkg.sibling import example
1
2
3하지만, 명시적 상대경로 가져오기는 절대경로 가져오기의 허용 가능한 대안이다. 특히, 불필요하게 장황하고 복잡한 패키지 레이아웃을 처리할 땐, 절대경로 가져오기를 사용하는 것보다 나을 수 있다.
from . import sibling from .sibling import example
1
2표준 라이브러리 코드는 복잡한 패키지 레이아웃을 피하고, 항상 절대경로 가져오기를 사용해야한다.
암시적인 상대경로 가져오기는 절대 사용되어선 안되며, Python 3 에서는 제거되었다.
클래스를 갖고 있는 모듈에서 클래스를 가져올 때, 다음과 같이 작성하는 것은 괜찮다.
from myclass import MyClass from foo.bar.yourclass import YourClass
1
2만약 이 철자가 로컬 이름과 충돌이 발생하면, 명시적으로 작성하자.
import myclass import foo.bar.yourclass
1
2그리고 "myclass.MyClass"와 "foo.bar.yourclass.YourClass"를 사용하자.
와일드 카드 가져오기(
from <module> import *
) 는 피해야한다. 이들은 네임스페이스 안에서 보여지는 이름들을 불분명하게 만들고, 독자와 많은 자동화 툴들에 혼선을 준다. 단, 와일드 카드 가져오기를 사용할 수 있는 사례가 하나 있다. 공개 API의 일부로 내부 인터페이스를 다시 게시(republishing)하는 경우다. (예를 들어, 선택적 가속기 모듈(optional accelerator module) 내로부터 온 정의로, 인터페이스의 순수 Python 구현을 덮어 쓰는데, 정확히 어떤 정의를 덮어 쓸지 미리 알 수 없을 때)이름을 이러한 방법으로 다시 게시할 때, 퍼블릭 그리고 내부 인터페이스에 관한 가이드라인 은 계속 적용된다.
# 모듈 레벨 던더 이름
던더들은 앞뒤로 두개의 밑줄(underscore)로 감싸진 이름으로, __all__
, __author__
, __version__
등이 있다. 모듈 레벨의 "던더들"은 모듈의 독스트링 다음, 모든 가져오기 구문 전에 있어야 한다. 단, from __future__
가져오기는 제외한다. Python의 future-imports 명령(mandates)은 모듈내에서 반드시 독스트링을 제외한 어떠한 코드들 보다도 전에 놓여져 있어야 한다.
"""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
2
3
4
5
6
7
8
9
10
11
12
13