PEP 7 – C 코드 스타일 가이드
- Author:
- Guido van Rossum <guido at python.org>, Barry Warsaw <barry at python.org>
- Status:
- Active
- Type:
- Process
- Created:
- 05-Jul-2001
- Post-History:
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
소개
이 문서는 Python의 C 구현을 이루는 C 코드에 대한 코딩 규칙을 제시합니다. 파이썬 코드 스타일 가이드라인을 설명하는 짝이 되는 정보성 PEP도 참고하십시오.
참고로, 규칙은 깨지라고 있는 것입니다. 특정 규칙을 어길 만한 두 가지 좋은 이유는 다음과 같습니다:
- 규칙을 적용하면, 규칙을 따르는 코드를 읽는 데 익숙한 사람에게조차 코드의 가독성이 떨어지는 경우입니다.
- 마찬가지로 규칙을 어기고 있는 주변 코드와 일관성을 유지하기 위한 경우입니다(아마도 역사적인 이유 때문일 것입니다) – 물론 이는 (진정한 XP 스타일로) 다른 사람이 어질러 놓은 것을 정리할 기회이기도 합니다.
C 표준
다음 표준을 따르십시오. 해당 표준에 없는 기능에는 CPython 전용 래퍼를 사용하십시오(예: _Py_atomic_store_int32, Py_ALWAYS_INLINE, Py_ARITHMETIC_RIGHT_SHIFT; 공개 헤더에서는 _Py_ALIGNED_DEF). 이러한 래퍼를 추가할 때는 지원되지 않는 컴파일러에 맞게 쉽게 조정할 수 있도록 만드십시오.
- Python 3.11 이상 버전은 선택적 기능 없이 C11을 사용합니다. 공개 C API는 C99 및 C++와 호환되어야 합니다.
(이 글을 읽는 사용자분들께 다시 한번 말씀드리면, 이 PEP는 스타일 가이드이며 이 규칙들은 깨지라고 있는 것입니다.)
- Python 3.6부터 3.10까지는 C89와 함께 엄선된 몇 가지 C99 기능을 사용합니다:
<stdint.h>와<inttypes.h>의 표준 정수 타입 고정 폭 정수 타입이 필요합니다.static inline함수- 지정 초기화자(타입 선언에 특히 유용함)
- 선언과 코드의 혼용
- 불리언
- C++ 스타일 한 줄 주석
- 3.6 이전의 Python 버전은 ANSI/ISO 표준 C(1989년 버전 표준)를 사용했습니다. 이는 여러 가지 중에서도 특히 모든 선언이 블록의 맨 앞에 와야 한다는 것을 의미했습니다.
일반적인 C 코드 규약
- GCC나 MSVC의 확장 기능과 같은 컴파일러 전용 확장을 사용하지 마십시오. 예를 들어, 줄 끝에 백슬래시 없이 여러 줄 문자열을 작성하지 마십시오.
- 모든 함수 선언과 정의는 완전한 프로토타입을 사용해야 합니다. 즉, 모든 인자의 타입을 명시하고, 인자가 없는 함수를 선언할 때는
(void)를 사용하십시오. - 주요 컴파일러(gcc, VC++ 및 기타 몇 가지)에서 컴파일러 경고가 발생하지 않아야 합니다.
- 새 코드에서는 매크로보다
static inline함수를 우선적으로 사용해야 합니다.
코드 레이아웃
- 들여쓰기에는 공백 4칸을 사용하고, 탭은 절대 사용하지 마십시오.
- 어떤 줄도 79자를 넘어서는 안 됩니다. 이 규칙과 앞의 규칙을 함께 지켰을 때 코드를 작성할 공간이 부족하다면 코드가 너무 복잡한 것입니다. 서브루틴을 사용하는 것을 고려하십시오.
- 어떤 줄도 공백으로 끝나서는 안 됩니다. 줄 끝에 의미 있는 공백이 필요하다고 생각된다면 다시 생각해 보십시오. 누군가의 편집기가 으레 그 공백을 삭제할 수 있습니다.
- 함수 정의 스타일: 함수 이름은 1열에, 가장 바깥쪽 중괄호도 1열에 두고, 지역 변수 선언 뒤에는 빈 줄을 둡니다.
static int extra_ivars(PyTypeObject *type, PyTypeObject *base) { int t_size = PyType_BASICSIZE(type); int b_size = PyType_BASICSIZE(base); assert(t_size >= b_size); /* type smaller than base! */ ... return 1; }
- 코드 구조:
if,for같은 키워드와 그 뒤에 오는 여는 괄호 사이에는 공백을 한 칸 두고, 괄호 안쪽에는 공백을 두지 않습니다. 중괄호는 C에서 생략을 허용하는 곳을 포함해 모든 곳에 필요하지만, 다른 이유로 수정하지 않는 코드에 중괄호를 추가하지는 마십시오. 새로 작성하는 모든 C 코드에는 중괄호가 필요합니다. 중괄호는 다음과 같은 형식으로 작성해야 합니다:if (mro != NULL) { ... } else { ... }
- return 문에는 불필요한 괄호를 붙이지 않아야 합니다:
return(albatross); /* incorrect */
대신 다음과 같이 작성하십시오:
return albatross; /* correct */
- 함수 및 매크로 호출 스타일:
foo(a, b, c)– 여는 괄호 앞에는 공백을 두지 않고, 괄호 안쪽에도 공백을 두지 않으며, 쉼표 앞에는 공백을 두지 않고, 각 쉼표 뒤에는 공백을 한 칸 둡니다. - 대입, 불리언, 비교 연산자 앞뒤에는 항상 공백을 두십시오. 연산자가 많이 쓰인 표현식에서는 가장 바깥쪽(우선순위가 가장 낮은) 연산자 앞뒤에 공백을 두십시오.
- 긴 줄 나누기: 가능하다면 가장 바깥쪽 인자 목록의 쉼표 뒤에서 줄을 나누십시오. 이어지는 줄은 항상 적절하게 들여쓰십시오. 예를 들면 다음과 같습니다:
PyErr_Format(PyExc_TypeError, "cannot create '%.100s' instances", type->tp_name);
- 긴 표현식을 이항 연산자에서 나눌 때는 중괄호를 다음과 같은 형식으로 작성해야 합니다:
if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 && type->tp_dictoffset == b_size && (size_t)t_size == b_size + sizeof(PyObject *)) { return 0; /* "Forgive" adding a __dict__ only */ }
특히 주변 코드와 일관성을 유지하기 위해서라면 연산자를 줄 끝에 두어도 괜찮습니다. (더 자세한 논의는 PEP 8을 참고하십시오.)
- 여러 줄로 된 매크로에서는 줄 연속 문자를 세로로 정렬하십시오.
- 문장처럼 사용하도록 만든 매크로에는
do { ... } while (0)매크로 관용구를 사용하되, 마지막 세미콜론은 붙이지 마십시오. 예시:#define ADD_INT_MACRO(MOD, INT) \ do { \ if (PyModule_AddIntConstant((MOD), (#INT), (INT)) < 0) { \ goto error; \ } \ } while (0) // To be used like a statement with a semicolon: ADD_INT_MACRO(m, SOME_CONSTANT);
- 파일 지역 매크로는 사용한 뒤
#undef처리하십시오. - 함수, 구조체 정의, 함수 내부의 주요 부분 앞뒤에는 빈 줄을 두십시오.
- 주석은 그것이 설명하는 코드 앞에 둡니다.
- 공개 인터페이스에 포함될 것이 아니라면 모든 함수와 전역 변수는 static으로 선언해야 합니다.
- 외부 함수와 변수는 항상 “Include” 디렉터리의 적절한 헤더 파일에 선언을 두며, 이 선언에는 다음과 같이
PyAPI_FUNC()매크로와PyAPI_DATA()매크로를 사용합니다:PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *); PyAPI_DATA(PyTypeObject) PySuper_Type;
명명 규칙
- 공개 함수에는
Py접두사를 사용하고, static 함수에는 절대 사용하지 마십시오.Py_접두사는Py_FatalError같은 전역 서비스 루틴을 위해 예약되어 있습니다. 특정 루틴 그룹(예: 특정 객체 타입 API)은 더 긴 접두사를 사용합니다. 예를 들어 문자열 함수에는PyString_접두사를 사용합니다. - 공개 함수와 변수는 밑줄을 포함한 MixedCase를 사용합니다. 예:
PyObject_GetAttr,Py_BuildValue,PyExc_TypeError. - 가끔 “내부” 함수가 로더에 보여야 하는 경우가 있습니다. 이럴 때는
_Py접두사를 사용합니다. 예:_PyObject_Dump. - 매크로는 MixedCase 접두사를 붙인 뒤 대문자를 사용해야 합니다. 예:
PyString_AS_STRING,Py_PRINT_RAW. - 매크로 매개변수는 C 변수 및 구조체 멤버와 쉽게 구별할 수 있도록
ALL_CAPS스타일을 사용해야 합니다.
문서화 문자열
- 독스트링 없이 Python을 빌드할 수 있도록(
./configure --without-doc-strings) 독스트링에는PyDoc_STR()또는PyDoc_STRVAR()매크로를 사용하십시오. - 각 함수 독스트링의 첫 줄은 인자와 반환값을 간략하게 요약하는 “시그니처 줄”이어야 합니다. 예를 들면 다음과 같습니다:
PyDoc_STRVAR(myfunction__doc__, "myfunction(name, value) -> bool\n\n\ Determine whether name and value make a valid pair.");
시그니처 줄과 설명 텍스트 사이에는 항상 빈 줄을 넣으십시오.
함수의 반환값이 (의미 있는 반환값이 없어서) 항상
None이면 반환 타입 표시를 포함하지 마십시오. - 여러 줄로 된 독스트링을 작성할 때는 위 예제처럼 백슬래시 줄 이음을 사용하거나 문자열 리터럴 연결을 반드시 사용하십시오:
PyDoc_STRVAR(myfunction__doc__, "myfunction(name, value) -> bool\n\n" "Determine whether name and value make a valid pair.");
일부 C 컴파일러는 둘 중 어느 것도 사용하지 않은 문자열 리터럴을 받아들이지만:
/* BAD -- don't do this! */ PyDoc_STRVAR(myfunction__doc__, "myfunction(name, value) -> bool\n\n Determine whether name and value make a valid pair.");
모든 컴파일러가 그런 것은 아닙니다. MSVC 컴파일러는 이에 대해 경고를 내는 것으로 알려져 있습니다.
Copyright
This document has been placed in the public domain.