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

Python 개선 제안 한국어 번역

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:


Table of Contents

번역·라이선스 안내

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

소개

이 문서는 Python의 C 구현을 이루는 C 코드에 대한 코딩 관례를 제공합니다. Python 코드에 대한 스타일 가이드라인을 설명하는 참고용 PEP인 style guidelines for Python code도 참조하십시오.

규칙은 어길 수 있다는 점에 유의하십시오. 특정 규칙을 어길 만한 타당한 이유는 두 가지입니다:

  1. 규칙을 적용하면 코드가 덜 읽기 쉬워지는 경우, 규칙을 따르는 코드를 읽는 데 익숙한 사람에게조차 그러한 경우.
  2. 마찬가지로 규칙을 어기고 있는 주변 코드와의 일관성을 유지하기 위한 경우(아마도 역사적인 이유 때문일 것입니다) – 다만 이는 (진정한 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까지는 몇 가지 선택된 C99 기능과 함께 C89를 사용합니다:
    • <stdint.h><inttypes.h>의 표준 정수 타입입니다. 고정폭 정수 타입이 필요합니다.
    • static inline 함수
    • 지정 초기화자(타입 선언에 특히 유용함)
    • 뒤섞인 선언
    • 불리언
    • C++ 스타일 줄 주석
  • 3.6 이전 버전의 파이썬은 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와 같습니다.
  • 매크로 매개변수는 ALL_CAPS 스타일을 사용해야 하며, 이는 C 변수 및 구조체 멤버와 쉽게 구별되도록 하기 위함입니다.

독스트링

  • 독스트링 없이 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 컴파일러는 이에 대해 오류를 낸다고 알려져 있습니다.