원본 문서 : https://www.python.org/dev/peps/pep-0008/
혼자 공부하면서 정리할 겸 요약했습니다.
중간중간 생략된 부분이 있을 수 있으며 오역, 의역 등이 있을 수 있습니다.
2. Code lay-out
Indentation(들여쓰기)
들여쓰기는 space 4번을 이용한다.
연속 되는 문장은 괄호(소, 중, 대)를 이용하여 수직 정렬을 하거나 'hanging indent'* 를 사용한다. 'hanging indent'를 사용할 경우, 첫번째 줄에는 인수가 오면 안되며 더 많은 들여쓰기를 통해 연속되는 문장임을 확실히 드러나게 해야한다.
*hanging indent : 정확하겐 모르겠지만 이어지는 문장에 첫 줄을 제외하곤 계속 들여쓰기를 하는 방법 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 예제: # 구분자(delimeters)를 이용한 정렬 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) # 'hanging indent'는 반드시 한 레벨을 추가한다. foo = long_function_name( var_one, var_two, var_three, var_four) 선택사항: 4칸 공백은 연속되는 줄에선 선택사항이다. # 'hanging indent'의 경우에는 4번 띄어쓰기 대신 다르게 사용가능 foo = long_function_name( var_one, var_two, var_three, var_four) | cs |
여러 줄로 표현 되는 if문의 경우, ‘if + single space + 괄호 + 4칸 들여쓰기 + 조건문들(multiple conditions)’식의 표현은 오히려 조건문과 if문 안의 중첩된 코드와의 구분을 어렵게 해 더 큰 혼란을 가져온다. PEP은 조건문과 if문 내의 문장과의 구분을 위한 명백한 표기법을 가지진 않고 여러가지 선택지를 제공한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 추가적인 들여쓰기를 사용하지 않음 if (this_is_one_thing and that_is_another_thing): do_something() # 주석을 추가해 조건문과 나머지 코드를 구분 if (this_is_one_thing and that_is_another_thing): # 두 조건문이 만족되면 아래를 실행 do_something() # 추가적인 들여쓰기를 통해 조건문과 나머지 코드를 구분 if (this_is_one_thing and that_is_another_thing): do_something() | cs |
여러 줄의 생성자의 닫히는 괄호(소, 중, 대)는 마지막 줄의 공백이 아닌 첫번째 문자(요소) 위치에 오거나 마지막 줄에서 생성자가 시작되는 첫번째 열에 위치한다.
1 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', ) my_list = [ 1, 2, 3, 4, 5, 6, ] result = some_function_that_takes_arguments( 'a', 'b', 'c', 'd', 'e', 'f', ) | cs |
Tap or Spaces?
들여쓰기는 space가 권장 된다.
tap은 이미 tap으로 들여쓰기가 사용된 코드에서만 단독으로 사용될 수 있다.
파이썬3은 space와 tap의 혼용을 금한다.
Maximum Line Length
모든 코드는 한 줄에 최대 79자까지 쓰는 것을 허용한다.
Doctrings 또는 주석은 72자까지 쓰도록 제한한다. 여러 줄로 길게 표현되는 문장은 괄호(소, 중, 대)를 이용해 여러 행으로 분리해 표현하는 것이 좋다. 어떠한 경우에는 백슬래시(backslash)를 사용해 연속 되는 문장의 줄바뀜을 표현하는 것이 적절하다. 아래의 긴 with문은 백슬래시를 사용하는 것이 적절하다.
1 2 3 | 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()) | cs |
assert문에서도 백슬래시가 유용하며 연속되는 문장을 명확하게 하기 위해 적절히 들여쓰기를 해야 한다.
Should a line break before or after a binary operator
PEP은 이항연산자의 줄바뀜 위치로써 연산자의 앞, 뒤 위치를 모두 허용한다. 하지만 연산자의 뒤에서 줄바꿈을 하는 것은 코드를 더욱 읽기 어렵게 하므로 연산자의 앞에서 줄바꿈을 하는 것을 더욱 권장한다. 그리고 연산자의 앞에서 줄바꿈을 하는 것이 최신 표현법이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 오래된 표현, 연산자의 뒤에서 줄바꿈 income = (gross_wages + taxable_interest + (dividends - qualified_dividends) - ira_deduction - student_loan_interest) # 최신 표현, 연산자의 앞에서 줄바꿈 income = (gross_wages + taxable_interest + (dividends - qualified_dividends) - ira_deduction - student_loan_interest) | cs |
Blank Lines(빈줄)
Top-level 함수와 클래스 정의부는 2개의 빈줄을 이용해 구분한다.
클래스안의 메소드는 한 개의 빈줄을 이용해 구분한다.
서로 연관된 함수와 코드 덩어리는 여러 개의 빈줄을 통해 구분하기도 하며 함수 내에서 논리적인 문단을 구분하기 위해 쓰이기도 한다. 다만 위의 두가지 예는 드물게 사용된다.
Source File Encoding
파이썬3은 항상 UTF-8방식을 사용한다.
UTF-8방식을 따르는 파이썬3 파일은 인코딩 방식의 정의가 필요하지 않다.
파이썬 표준 라이브러리에서는 non-ASCII 문자를 테스트용도나 Docstring에서 코드작성자의 이름을 표현하는 것 외에는 사용하지 않는다. 그러나 문자열 상수에서 non-ASCII문자를 사용해야 한다면 '\x, \u, \U, \N' 등의 이스케이프를 사용하도록 한다.
파이썬3 이상의 버전에서는 ASCII로만 이루어진 식별자를 사용해야하며 반드시 영어 단어를 쓰도록 권장한다. 문자열 상수와 주석도 반드시 영어를 사용한다. 다만 몇가지 예외가 있는데 non-ASCII 문자 사용을 테스트하는 코드나 non-ASCII 문자 형식의 사람이름을 사용해야할 경우이다. non-ASCII 문자 형식의 사람 이름을 사용할 땐, 알파펫으로 번역한 이름도 반드시 포함해야 한다.
Import(임포트)
임포트는 반드시 행을 분리해서 선언한다.
1 2 3 4 | Yes: import os import sys No: import sys, os | cs |
그러나, 다음의 경우는 허용된다.
1 | from subprocess import Popen, PIPE |
임포트는 파일 상단의 파일 주석과 Docstring 바로 아래, 그리고 전역변수, 상수 선언부 위에 위치한다.
임포트는 아래의 순서로 그룹지어 진다.
- standard library imports
- related third party imports
- local application/libarary specific imports
임포트 그룹 각각은 빈 줄 하나로 구분한다.
임포트는 절대경로를 이용한 절대 임포트가 권장된다. 이는 가독성도 높혀주고 동작도 더 잘 되도록 한다.
1 2 3 | import mypkg.sibling from mypkg import sibling from mypkg.sibling import example | cs |
그러나 복잡한 레이아웃을 가진 패키지에서 임포트를 할 경우에는 절대 임포트 대신 상대경로를 이용한 명시적 상대 임포트가 허용된다.
1 2 | from . import sibling from .sibling import example | cs |
standard library에선 복잡한 패키지 레이아웃을 피하도록 하며 항상 절대 임포트를 사용한다.
파이썬3 에서는 암시적 상대 임포트(implicit relative import)는 없어졌다.
클래스가 정의된 모듈에서 클래스를 임포트할 경우에는 보통 아래처럼 사용한다.
1 2 | from myclass import MyClass from foo.bar.yourclass import YourClass | cs |
만약 임포트한 클래스의 이름이 지역 변수와 충돌한다면 아래 처럼 사용한다.
1 2 | import myclass import foo.bar.yourclass | cs |
Module level dunder names
모듈 레벨의 dunder(앞 뒤로 밑줄 2개씩 있는 것 ex : __all__, __future__ 등등...)은 Docstring 뒤에 그리고 import문 앞에 와야한다.
단, from __future__ import 는 docstring 바로 뒤에 그 어떤 코드보다 먼저 위치해야한다. 그 뒤에 dunder가 위치한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | For example: """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 | cs |
3. String Quotes(따옴표)
파이썬 코드에서는 문자열을 표현할 때 큰 따옴표, 작은 따옴표 아무거나 사용하면 된다. 다만 문자열 안에서 따옴표(큰 or 작은)를 표현해야 할 때, 가독성을 위해서 이스케이프 문자(백슬래시)사용을 피하도록 적절히 따옴표를 선택하도록 하자.
세 개의 따옴표를 사용할 때에는 반드시 쌍따옴표를 사용해 표기하자. (ex : """)
4. Whitespace in Expressions and Statements
Pet peeves(골치덩어리)
아래와 같은 상황에서 무의미한 공백을 피하자
- 괄호(소, 중, 대) 안의 양쪽 끝
1 2 | Yes: spam(ham[1], {eggs: 2}) No: spam( ham[ 1 ], { eggs: 2 } ) | cs |
- 콤마, 세미콜론, 콜론 바로 앞
1 2 | Yes: if x == 4: print x, y; x, y = y, x No: if x == 4 : print x , y ; x , y = y , x | cs |
- 슬라이스에서 콜론은 우선순위가 낮은 이항연산자와 유사한 방식으로 사용되며 양쪽에 동일한 공간을 할당해야된다. 확장된 슬라이스에서 모든 콜론은 같은 크기의 공간이 할당되어야 한다. 다만, 피연산자가 누락되었을 경우에는 공백 또한 주지 않는다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Yes: 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] No: ham[lower + offset:upper + offset] ham[1: 9], ham[1 :9], ham[1:9 :3] ham[lower : : upper] ham[ : upper] | cs |
- 함수 호출 시 뒤 인자를 넣기 위한 소괄호의 바로 앞
1 2 | Yes: spam(1) No: spam (1) | cs |
- 리스트나 사전의 인덱스나 슬라이스에 사용되는 대괄호의 바로 앞
1 2 | Yes: dct['key'] = lst[index] No: dct ['key'] = lst [index] | cs |
- 대입 연산자의 앞뒤는 공백을 주자
1 2 3 4 5 6 7 8 9 10 11 | Yes: x = 1 y = 2 long_variable = 3 No: x = 1 y = 2 long_variable = 3 | cs |
기타 유의사항
문장의 마지막에 따라오는 공백을 없게 하자. 잘 안보이기 때문에 혼란이 생길 수 있다. 예로 백슬래시 뒤에 오는 공백이나 줄바꿈은 문장이 이어지는 것을 표현하는 마커역할을 하지 못한다.
- 모든 이항연산자(대입, 증감, 비교, 부울) 앞뒤로는 공백을 두자.
- 우선순위가 다른 연산자를 동시에 사용할 경우에는 낮은 순위의 연산자에 공백을 주자. 연산자에 공백을 주는건 너의 적절한 판단에 맡기지만, 그러나 절대로 한 칸을 초과하는 공백을 사용하지는 않으며 이항연산자의 양쪽은 같은 공백을 갖도록 하자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Yes: i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (a-b) No: i=i+1 submitted +=1 x = x * 2 - 1 hypot2 = x * x + y * y c = (a + b) * (a - b) | cs |
- 키워드 인자나 디폴트 인자에 사용되는 대입연산자는 절대로 공백을 사용하지 않는다
1 2 3 4 5 6 7 8 | Yes: def complex(real, imag=0.0): return magic(r=real, i=imag) No: def complex(real, imag = 0.0): return magic(r = real, i = imag) | cs |
- function annotation에 사용되는 콜론은 기존의 룰을 따르며, '->'는 양 옆에 공백을 한 칸씩 가진다.
1 2 3 4 5 6 7 8 9 | Yes: def munge(input: AnyStr): ... def munge() -> AnyStr: ... No: def munge(input:AnyStr): ... def munge()->PosInt: ... | cs |
- argument annotation을 디폴트 변수에 사용할 때, 기존의 디폴트 변수에 사용할때의 공백 없는 대입연산자완 다르게 대입연산자 앞 뒤에 공백을 한 칸씩 가진다.
1 2 3 4 5 6 7 8 9 | Yes: def munge(sep: AnyStr = None): ... def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ... No: def munge(input: AnyStr=None): ... def munge(input: AnyStr, limit = 1000): ... | cs |
- 여러 구문이 한 줄에 오는 것은 보통 권장하지 않는다.
1 2 3 4 5 6 7 8 9 10 11 | Yes: if foo == 'blah': do_blah_thing() do_one() do_two() do_three() Rather not: if foo == 'blah': do_blah_thing() do_one(); do_two(); do_three() | cs |
- 그러나 가끔 짧은 몸체의 if, for, while 문에서는 여러 구문을 한 줄에 써도 되지만 절대로 여러 줄의 절에서는 한 줄에 쓰면 안된다. 또한 긴 줄에서 폴딩을 피해라
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Rather not: if foo == 'blah': do_blah_thing() for x in lst: total += x while t < 10: t = delay() Definitely not: 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() | cs |
5. Comments(주석)
주석은 코드가 업데이트 될 때마다 반드시 같이 업데이트 해야 한다.
주석은 반드시 완전한 문장형태여야 한다. 만약 주석이 구문이거나 한 문장일 경우, 첫 글자는 대문자를 쓴다. 그러나 이 주석에 사용되는 첫 단어가 소문자 식별자인 경우에는 그대로 소문자를 쓴다.
주석이 짧을 경우에는 마침표가 생략될 수 있다. 블록 주석의 경우에는 주로 완전한 문장을 사용하며 문장의 마지막은 마침표로 끝난다.
마침표 뒤에는 두 칸의 공백을 준다.
주석은 영어로 쓰도록 하자.
Block Comments
블록 주석은 뒤에 따라오는 코드에 대한 설명이며 뒤에 따라오는 코드와 들여쓰기 수준을 맞춘다.
모든 줄은 # 뒤에 한 칸 공백을 주고 작성한다.(주석 안 들여쓰기된 텍스트가 있을땐 제외)
블록 주석의 문단은 #기호 한줄로 구분한다.
Inline Comments
인라인 주석은 잘 사용되지 않는다.
인라인 주석은 한 구문과 같은 줄에 쓰는 주석을 뜻한다. 인라인 주석은 구문과 적어도 2칸 이상의 공백으로 구분되야하며 # 기호와 한 칸 공백을 주고 작성을 시작한다.
명백한 상황에서의 주석은 불필요하며
1 | x = x + 1 # Increment x | cs |
때때로 이런 경우에는 도움이 된다.
1 | x = x + 1 # Compensate for border | cs |
Documentation Strings
public 모듈, 함수, 클래스, 메소드에 대해서는 Docstrings을 작성하도록 하자. non-public 메소드에 대해서는 Docstring이 필요가 없다. 다만 메소드가 무슨 역할을 하는지 주석을 작성하는 것이 좋은데, def문장 바로 아래줄에 위치하도록 하는 것이 좋다.
Docstrings 마지막 줄은 """ 기호 한줄로 끝내자.
1 2 3 4 | """Return a foobang Optional plotz says to frobnicate the bizbaz first. """ Colored by Color Scripter | cs |
한 줄짜리 Docstrings는 같은 줄이 마지막에 """ 기호를 사용해 끝내도록 하자.
6. Naming Conventions
파이썬 코드의 명명규칙은 매우 복잡하기에 완전히 일정하게 정하지는 않는다. 그럼에도 최근의 표준 명명법은 있다. 기존에 작성된 코드는 그 코드의 명명법을 따르도록 하고, 앞으로 작성될 코드엔 아래의 규칙을 따르도록 하자.
Overriding Principle
사용자에게 public API로 보여지는 이름은 그 구현보다는 사용법을 나타내도록 명명하는 것이 좋다.
Descriptive Naming Styles
다양한 명명규칙들이 있다.
- b (소문자 하나)
- B (대문자 하나)
- lowercase
- lower_case_with_underscore
- UPPERCASE
- UPPER_CASE_WITH_UNDERSCORE
- CapitalizedWords(or CapWords or CamelCase) note: CapWords에서 약어를 쓸 땐, 전부 대문자로 쓴다.
- mixedCase(CapWords와 다름, 첫 글자가 소문자)
- Capital_Words_With_Underscores (별로...)
- _single_leading_underscore : 드물게 내부에서 사용하는 지시자이다. 예를 들어 from M import * 에서 언더스코어를 사용한 객체는 임포트하지 않는다.
single_trailing_underscore_ : 파이썬 키워드와의 충돌을 막기 위해 쓴다.
1 | Tkinter.Toplevel(master, class_='ClassName') | cs |
- __double_leading_underscore : 클래스 attribute를 명명할때 사용, 변수를 mangling하게 한다.(FooBar 클래스 안의 __boo는 _FooBar__boo가 된다.) 아래 내용 참조
- __double_leading_and_trailing_underscore__ : 'magic 객체', 사용불가, 미리 정의되어 있는 이름만 사용 가능하다
Names to Avoid
한 글자 변수명으로 l(소문자 엘), O(대문자 오), I(대문자 아이)를 사용하지 않는다. 특정 폰트에서 숫자 1, 0으로 헷갈릴 수 있다.
I(대문자 아이)를 써야한다면 L(대문자 엘)을 쓰도록 하자.
Package and Module Names
모듈이름은 짧아야 하고 모두 소문자를 사용하며, 가독성을 위해 언더스코어가 쓰일 수 있다. 패키지 이름도 짧아야 하고 모두 소문자를 사용하지만 언더스코어는 사용하지 않는다.
C/C++로 작성된, 고수준 객체지향 인터페이스를 제공하는 파이썬 모듈을 수반하는 경우엔 모듈 이름에 언더스코어가 쓰일 수 있다, (예 _socket)
Class Names
클래스이름은 CapWords 방식을 따른다.
인터페이스가 정의 되어 있거나 callable로서 우선적으로 사용되는 경우에는 함수명명법이 대신 사용된다.
builtin 이름에 대해서도 다른 규칙이 있다. 대부분의 builtin 이름은 한 단어(혹은 연속된 두 단어)이어야 하고 예외 이름과 builtin 상수에 대해선 CapWords 방식이 사용된다.
Type variable names
타입 변수 이름은 짧은 CapWords 방식을 사용한다.(T, AnyStr, Num) covariant or contravariant 임을 나타내기 위해 변수의 접미사로 _co or _contra 가 사용된다.
1 2 3 4 | from typing import TypeVar VT_co = TypeVar('VT_co', covariant=True) KT_contra = TypeVar('KT_contra', contravariant=True) | cs |
Exception Names
예외도 클래스이기 때문에 클래스 명명규칙을 따른다. 그리고 접미사 'Error'를 붙인다.(실제로 그 예외가 에러일 경우)
Global Variable Names
(전역 변수가 한 모듈에서만 사용된다고 가정하자) 이 규칙은 함수에 적용되는 것과 동일하다.
'from M import *' 을 사용하도록 설계된 모듈에서는 '__all__'을 사용해, 다른 모듈에서 사용되는 것을 막거나, 예전 규칙인 언더스코어를 이름 앞에 붙여 사용해 'non-public' 임을 나타내라.
Function Names
함수명은 소문자를 사용하며 가독성을 위해 언더스코어로 단어를 구분한다. 이미 mixedCase를 많인 사용한 모듈의 경우, 그 모듈에 한해서 mixedCase를 허용한다.
Function and method arguments
인스턴스 메소드의 첫 인수로 반드시 self를 쓴다.
클래스 메소드의 첫 인수로는 반드시 cls를 쓴다.
인수명이 키워드와 충돌될 경우, 인수명을 축약하거나 인수명을 조금 변경하는 것 보다는 인수명 뒤에 언더스코어를 붙여 사용하자. 'clss' 보다는 'class_'가 더 좋은 표기이다. 제일 좋은 방법은 충돌이 없게끔 동의어로 이름을 짓는 것이다.
Method Names and Instance Variable
함수명명규칙을 따른다. (언더스코어를 사용한 소문자 표기)
non-public 메소드, 인스턴스 변수에는 언더스코어 하나를 앞에 붙인다.
서브클래스와의 충돌을 피하기 위해 앞에 언더스코어를 2개 붙여 파이썬 이름 mangling규칙을 따르도록 한다.
파이썬은 다음과 같은 mangling 규칙을 따른다. 만약 'Foo' 클래스 안에 '__a'인 어트리뷰트가 있다면 'Foo.__a'의 형태로 접근이 불가능하다. 일반적으로 이름 앞 언더스코어를 2개 붙이는 방식은 주로 서브클래스로 사용되도록 디자인 된 클래스의 어트리뷰트와의 이름충돌을 막기 위해 사용한다.
Constants
상수는 주로 모듈레벨에서 정의되며 언더스코어를 이용한 대분자 표기법을 사용한다.
예로 MAX_OVERFLOW, TOTAL과 같은 방식으로 표기한다.
Designing for inheritance
항상 클래스의 메소드와 어트리뷰트를 public으로 할지 non-public으로 할지 정해라. 만약 불확실하다면 non-public으로 정해라. 차후에 non-public에서 public으로 변경하는 것이 그 반대보다 훨씬 수월하기 때문이다.
public 어트리뷰트는 관련 없는 클라이언트가 직접 사용할 수 있는 것을 뜻하며, 내부에 양립할 수 없는 변화(?)를 피하도록 보장해야 한다. non-public 어트리뷰트는 서드파티에 의해 사용되지 않도록 의도된 것이나 non-public 어트리뷰트가 수정되지 않거나 지워지지 않는 것은 보장되지 않는다.(수정, 삭제가 가능하다는 뜻 같다.)
파이썬에서는 'private'이란 말을 쓰지 않는다. 파이썬엔 진짜 'private'한 어트리뷰트는 없다.(일반적으로 불필요한 작업을 거치지 않는 이상)
다른 종류의 어트리뷰트로는 서브클래스 API가 있다.(다른 언어에서는 주로 'protected'라 불린다.)
몇몇 클래스들은 상속을 통해 확장하거나 수정해 사용하도록 디자인 되어 있다. 이런 클래스를 디자인 할때에는 어떤 어트리뷰트를 public으로 할지, 어떤 부분은 subclass API로 할지, 어떤 부분은 부모 클래스(base class)에서만 사용되도록 할지 명확하게 결정하도록 하자.
다음과 같은 파이썬의 가이드라인을 따르도록 하자.
- public 어트리뷰트는 앞에 언더스코어를 사용하지 않는다.
- 만약 public 어트리뷰트의 이름이 기존 키워드와 충돌된다면 이름 끝에 언더스코어를 하나 붙여 사용하자. 이것은 이름을 축약하거나 변경하는 것보다 권장되는 방식이다. (그러나 'cls'의 경우에는 이름은 클래스 메소드의 첫번째 인자로 'class'를 의미하는 것으로 기존의 방식인 'class_'를 사용하는 것보다 권장된다.)
- 단순한 데이터 어트리뷰트의 경우에는 복잡한 accessor / mutator를 사용하기 보단 어트리뷰트 이름으로 직접 접근하도록 하자. 파이썬은 추후 개선에 있어 쉬운 방법을 제공하며, 단순한 데이터 어트리뷰트는 함수 기능이 늘어나는것이 필요함(?)을 알아야 한다. 이런 경우에는 properties를 사용해 단순한 데이터 어트리뷰트 접근 문법 뒤에 함수 구현을 숨겨라.
- 만약 너의 클래스가 서브클래스로 사용되는 클래스이며, 서브클래스에서 사용되길 원치 않은(비상속) 어트리뷰트를 가지고 있을 땐, 이름 앞에 언더스코어를 2개 붙이는 것을 고려하라. 이것은 파이썬의 어트리뷰트 이름에 mangling 규칙이 작용하게 해, 우연히 서브클래스에서 어트리뷰트 이름이 겹치는 경우를 방지한다.
backwards compatibility guarantees(?)는 오직 public 인터페이스에만 적용된다. 따라서 사용자가 public 인터페이스와 internal 인터페이스를 명확히 구분할 줄 아는 것은 중요하다.
인터페이스의 문서가 임시적이지 않거나, backwards compatibility guarantee가 제외되지 않은 internal 인터페이스의 경우, 문서화 된 인터페이스는 public 으로 고려된다. 문서화되지 않은 인터페이스는 모두 internal으로 여겨진다.
우수한 개선지원을 위해, 모듈은 반드시 __all__ 어트리뷰트를 사용해 public API의 이름을 명시적으로 표기해야 한다. __all__ 어트리뷰트에 빈 리스트를 설정한다면 이 모듈은 public API가 없는 모듈이 된다.
__all__ 어트리뷰트를 적절히 설정했다 하더라도 패키지, 모듈, 클래스, 함수, 어트리뷰트, 이 외의 이름들 모두 앞에 언더스코어 한 개가 붙으면 이 또한 internal 인터페이스가 된다.
포함하는 namespace(패키지, 모듈 또는 클래스)가 internal로 여겨진다면 이를 포함하는 인터페이스도 internal이다.