Pythonに関する誤解

最近、またPythonに関する誤解が広がっている気がするのでちょっとまとめて置く。

メソッド定義のselfはなぜ書かないといけないの?
- 古参言語の多くは確かに省略するのが一般的
- 新参のGoやRustは省略しないという手法を採りました
- どっちが主流とは言えない状況と言える
- OOPとはこうでなくてはならないと考える人が結構いる
- Class概念が必須であり、オブジェクトの操作は全てメソッドで定義すべきみたいな
- 過去、JavaScriptはプロトタイプ方式でOOPを実現していた(今はclassを備えたけど)
- PythonとりわけGoやRustは古参がはぐくんだ純粋なOOPとは若干かけ離れた仕様
- だからと言ってOOPできないわけではなく、これらはいずれもOOPを強力に支援する仕様がある
- Pythonのselfはコア開発者Guidoがそのメリットをしっかり議論して残しており、なくすこともできたがあえて残したとされている
- OOP機能を実装する時に怠惰な理由でselfの記述を残したわけではない

NumPyはなぜオブジェクト指向で実装されていないの?
- NumPyはオブジェクト指向プログラミングを活用して実装されていますので誤解です
- コアクラスndarrayは継承してメタデータを追加するといった事例もあり、ちゃんとOOPに乗っ取った拡張が可能
- 多くの機能がモジュール関数で提供されているのがパフォーマンス問題があるからなんて指摘があったりしますが、単に拡張していくのに都合がいいから
- 確かに極めて小さなオーバーヘッドがメソッドコールには載りますが、それを気にしてのことじゃない
- その影響が無視できないのは微小な処理を高頻度に呼び出すようなものだけですが、NumPyの設計思想はそういう微小な処理はC拡張の中で行うようにデザインされているので上記のオーバーヘッドの影響は無視できる
- 逆にメソッドで拡張機能を実装するメリットを問うてみたほうがいいそれがメソッドであるメリットはほとんどない
- いつ何時もオブジェクトを示してから動詞的にメソッドを呼びたいと考えるのは「にわかオブジェクト指向脳」の悪いところ
- そのメソッドが継承先の子々孫々にまで必要な機能かどうか考えたことがあるのかどうか(できるかどうかではなく、必要かどうか)
- できたらいいなでコードを書くことはのちに保守コストを引き上げることをNumPy開発メンバーはわかっているからモジュール関数で豊富な機能を提供する方法を選んだ

Pythonのlen関数はなぜメソッドにしなかった?
Pythonのlen関数がメソッド(たとえば obj.len())ではなく関数(len(obj))として設計された理由は、コードの一貫性と可読性、そして使いやすさを重視したためです。
デザイン上の理由
一貫性のある記法:どのシーケンス型やコレクション型に対しても、同じようにlen(obj)記法で長さを取得でき、型ごとに異なるメソッド名(例:.length(), .size(), .count()など)を覚える必要がありません。読みやすさ:読み手が「長さ」や「要素数」を取得する意図を直感的に把握しやすくなります。abs, min, max, sumなどの他の基本的な性質を取得する組み込み関数とも統一感があります。
インターフェースの統一:メソッドにすると各クラスごとに名前がバラバラになる可能性がありますが、len()関数ならば一貫してlen(obj)で済みます。
実装面の理由
特定のインタフェースに依存しない:Pythonでは各オブジェクトが__len__メソッドを実装することでlen()関数に対応します。メソッドとして直接生やすより「長さを問うインターフェース」だけを統一して外部に提供できます。明確な失敗:長さの意味がない型には適用できず、len()を使おうとするとすぐTypeErrorが出るため、バグを早く検知しやすい点もメリットです。
歴史的・思想的背景
直感的でやさしい言語設計:Guido van Rossum(Pythonの生みの親)は、シンプルで直感的に読めるコードを重視してこの設計を選びました。他言語との差別化:lengthやsizeなどのプロパティやメソッドを使う他言語と比較して、Pythonでは関数型で統一することで「型を問わず同じ感覚で扱える」ことを意識的に選んでいるといえます。
まとめ
- len()関数は「短く、一貫性があり、読みやすい」コードのために関数型で採用されている
- 各型で違うメソッド名になる混乱や、クラスによるバラツキを防ぐ意図もある
- Pythonの“直感的でやさしい”デザイン哲学を反映している
このような背景から、Pythonのlen関数はあえてメソッドにはされていません。