友達とPythonのコーディング規約の話をしていて、ふと「PythonのPEP8では関数名は小文字で書けと書かれているのに、なぜ一部のライブラリ( logging
など)ではcamelCaseが採用されているのか?」という話題になりました。
# loggingのコードの例。getLoggerなどのメソッド名がcamelCaseです。
import logging
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
実際、PEP8の「関数や変数の名前」には次のように書かれています。
関数の名前は小文字のみにすべきです。また、読みやすくするために、必要に応じて単語をアンダースコアで区切るべきです。
変数の名前についても、関数と同じ規約に従います。
mixedCase が既に使われている (例: threading.py) 場合にのみ、互換性を保つために mixedCase を許可します。
「一部のライブラリでは既にcamelCaseが使われててすまんの(意訳)」って書かれています。ちょっと気になったのでそのあたりの経緯をまとめてみました。先に結論を言うと、
- Javaのライブラリの影響を受けた
- PEP8の策定と同時期かそれ以前に開発された
- 互換性を重視して修正されていない
ことが理由でした。
loggingはJavaを参考にしてPEP8策定と同時期に開発された
stackoverflowの「How come the Python's logging module doesn't follow PEP8 conventions?」の回答で知ったのですが、 logging
は元々Javaの Log4j
を参考に実装されているそうです。実際にPEP282に「影響を受けたライブラリ」として挙がっていることも確認できました。
TECHSCOREの記事にある Log4j
のコードを見るに、ほとんどそのままですね。
// インスタンスの生成
Logger logger=Logger.getInstance(Sample.class.getName());
// ログレベルが WARN 以上の場合にログイベントが発生するように設定
logger.setLevel(Level.WARN);
//ログ出力
logger.info("This is info.");//出力されない
logger.warn("This is warn.");//出力される
logger.error("This is error.");//出力される
また「2001年に既にloggingが開発されていて、PEP8が策定された時期と同時期だったから」という理由も書かれています。
また、wikiによると開発者の間でもPEP8に違反していることは知られているようですが、プロジェクト内の一貫性や後方互換性を重視して今の所修正されていないようです。
API uses camelCase (goes against PEP8 recommendation and most of the stdlib)
- PEP8 says - consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is most important.
- It's a low priority right now, unless there's an initiative to ensure the rest of the stdlib is made to conform to PEP8. -- VinaySajip
このwikiでlogging2
というライブラリに触れられています。こちらでは「log4jより良い」って思いっきり書かれていますw
A More Pythonic Logging System; or, You Deserve Better Than log4j
threadingライブラリについて
PEP8で「mixedCase が既に使われている場合」の例として挙げられていた threading
についても調べてみました。Python3.8のドキュメントでは「camelCaseも後方互換性のために採用している」程度の書かれ方です。
ここには載っていませんが、Python 2.x シリーズでこのモジュールの一部のメソッドや関数に使われていた camelCase 名は、まだこのモジュールでサポートされます。
Python2.7ではこのように書かれていました。
Python 2.6 からこのモジュールは Java のスレッディング API の影響を受けた camelCase のプロパティを置き換える PEP 8 に準拠したエイリアスを提供します。この更新された API は multiprocessing モジュールのものと互換です。しかしながら、 camelCase の名称の廃止の予定は決まっておらず、 Python 2.x と 3.x の両方でサポートされ続けます。
こちらは互換性を保ちつつ、徐々にPEP8に準拠した形で移行していますね。logging
ライブラリも threading
同様、徐々にPEP8に準拠した形に移行していってほしいですね。
また、ドキュメントによると、このライブラリもJavaの強い影響を受けているようです。
このモジュールのおおまかな設計は Java のスレッドモデルに基づいています。とはいえ、 Java がロックと条件変数を全てのオブジェクトの基本的な挙動にしているのに対し、 Python ではこれらを別個のオブジェクトに分けています。