ビギナー
これからPythonっていう言語の勉強を始めようと思うんですけど・・・

先生
うん。

ビギナー
ブログとかを読んでたら、PEP?ってものがよく出てくるんです。

先生
ああ、あるね。

ビギナー
あれなんですか?読んでたほうがいいんですか?

先生
PEPはコーディングの規則や新しくこんな機能つけるよーなんていう情報をまとめた文書だね。

先生
だから読んでおいて損はないと思うよ。

ビギナー
う…でも英語なんですよね。どうにかしてください。

先生
….わかりました。(はぁ)

PEP(Python Enhancement Proposal)はPythonを改良する案、リリーススケジュール、コーディングスタイルなど開発を円滑に進める上で重要なことを文書にまとめておく場所。ここには、Pythonをコーディングするすべての人にとって重要な内容がきっと入っているはず。ビギナーが言うようにもちろん、英語。よって、これをできるだけ毎日、翻訳しながら読み解きまとめていくことで備忘録としていきたいと思います。英語は非常に苦手なので誤訳はご指摘ください。

※以下、アイコンが出てくる箇所は私のコメントになります。それ以外は、翻訳または翻訳のまとめです。

基本情報

Style Guide for C Code

PEP: 7
Title: Style Guide for C Code
C言語のコードスタイルガイド
Author: Guido van Rossum <guido at python.org>, Barry Warsaw <barry at python.org>
Status: Active
Type: Process
Created: 05-Jul-2001

イントロ

この文書はPythonのCの実装を構成するCコードのコーディング規約を定義します。Pythonコードのスタイルガイドラインを説明しているPEPを見てください[1]。
注)ルールは順守しなければならないものではありません。以下の2つの正当な理由を基にルールが破られる可能性があります。

  1. 1.ルールを適用することによって、ルールに慣れている人でも、可読性が悪くなってしまう時。
  2. 2.(おそらく歴史的な理由で)周囲のコードと一貫性を保つ時。
     これは(本当のXPスタイルで)他の人の混乱を避けるための処置です。

Cのルール

  • 3.6より前のバージョンのPythonでは、ANSI/ISO標準のC(1989年版)を使用します。(他の多くのことの中でも)すべての宣言がブロックの先頭にある必要があることを意味します(必ずしも関数の先頭にあるとは限りません)。
  • 3.6以上のバージョンのPythonは、いくつかC99の機能を備えたC89を使用します。
    • “stdint.h”と”inttypes.h”の整数型。固定幅整数型が必要なため。
    • 静的インライン関数
    • 指定イニシャライザ(特に型宣言に適している)
    • 混在宣言
    • ブーリアン型
    • C ++スタイルの行コメント

    C99機能は、コンパイラのサポートに次第で将来このリストに追加される可能性があります(主にMSVC)。

  • GCC拡張を使用しません。たとえば、バックスラッシュなしで複数行の文字列を記述しないなど
  • すべての関数の宣言と定義は完全なプロトタイプを使用します。すべての引数の型を指定します。
  • Python 3.6以降では、C++スタイルの『//』で1行コメントのみを使用します。
  • 主要なコンパイラ(gcc、VC ++、その他いくつか)についてのコンパイラ警告は行いません。

コードのレイアウト

  • 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;
    }

  • コード構造ifforなどのキーワードと条件文()間に1つのスペースが必要、ただし()の内側にスペースは不要です。中括弧はCで省略することが許可されている場合でも必要ですが、あなたが変更していないコードにわざわざ追加する必要はありません。新しく記述するCコードには中括弧が必要です。中括弧は、次のようにフォーマットします。
    if (mro != NULL) {
        ...
    }
    else {
        ...
    }
    

  • return文に冗長な括弧を付けません。
    return albatross; /* correct */
    return(albatross); /* incorrect */

  • 関数呼び出しとマクロ呼び出しのスタイル(の前に空白はなし、(の後ろも空白なし、カンマの前に空白も空白なし、コンマの後は空白を1つ入れます。
    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 */
    }

  • 関数、構造体定義、および関数内の主要なセクションの前後に空白行を置きます。
  • コメントは記述するコードの前に置きます。
  • すべての関数とグローバル変数は、公開されているインタフェースの一部にならない限り、静的に宣言します。
  • PyAPI_FUNC()マクロを使った外部の関数や変数については、”Include”ディレクトリの適切なヘッダファイルを宣言します。
    PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *);

命名規則

  • パブリック関数には接頭辞”Py“を使用します。しかし静的関数には使用しません。接頭辞”Py_“は、”Py_FatalError“のようにグローバルサービスルーチン用に使われています。また、特定のルーチンのグループ(特定のオブジェクトタイプのAPIなど)では、(文字列関数なら”PyString_“のように)より長い接頭辞を使用しています。
  • パブリック関数と変数は、”PyObject_GetAttr“、”Py_BuildValue“、”PyExc_TypeError“のように、アンダースコア付きのMixedCaseを使用します。
  • 時折、「内部」関数がローダーに見えなければならないときがあります。これは接頭辞”_Py”を使用します(例:_PyObject_Dump)。
  • マクロはMixedCaseで接頭辞を付けてから大文字を使用します。例えば、”PyString_AS_STRING“、”Py_PRINT_RAW“です。

ドキュメンテーション文字列

  • ドキュメンテーション文字列を使わずにPythonをビルドするときは、PyDoc_STRPyDoc_STRVAR()マクロをドキュメンテーション文字列に使います(./configure --without-doc-strings)。2.3より古いバージョンのPythonをサポートする必要があるCコードの場合は、Python.hをインクルードした後にインクルードできます。
    #ifndef PyDoc_STR
    #define PyDoc_VAR(name)         static char name[]
    #define PyDoc_STR(str)          (str)
    #define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str)
    #endif

  • 各関数のドキュメンテーション文字列の最初の行は、引数と戻り値の簡単な概要を示す”シグネチャ”であるべきです。
    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コンパイラはこれについて注意を促すことが知られています。

管理人
私は、Cについてあまり知らないのでもしかしたら頓珍漢なことを言っているかもしれません。何か気づいた際はコメントをお願いします。

リファレンス

[1] PEP8, “Style Guide for Python Code”, van Rossum, Warsaw (http://www.python.org/dev/peps/pep-0008)

1件のコメント

  1. ピンバック: 【Python】PEPを訳して読むーPEP0【ほぼ日】 | 趣味で始める機械学習

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です