もともと以下の記事のコメントに書いていたのですが、コメントに書くには攻撃的すぎる内容だと思ったので、ここに移しました。
Pythonで型を極める【Python 3.9対応】
宗教論争を引き起こすだけ、であろうことは承知の上での記事です。
最近、静的型付けの利点(というか、動的型付けの欠点?)がよく語られるようになってきて、TypeScript が隆盛したり、Pythonでも静的な型チェックができるようになっています。
ただ、個人的に、(とくに動的型付け言語に、後から追加された静的型チェック機能において)、「不要な型付け」(場合によっては、むしろ「有害にすら思える型付け」)をしているコードが増えているような気がしています。
Pythonで型を極める【Python 3.9対応】
の記事で、
def add(a, b):
"""引数を足した結果を返す"""
return a + b
に型を付けて
def add_type(a: int, b: int) -> int:
"""引数を足した結果を返す"""
return a + b
とする、という例が登場します。
しかしながら、この例では、型は書くべきではないと思います。
不必要に型を特定するのは良くないです。
この場合、a+b
という演算に意味があるような型であればよいのであって、intに特定するのは「悪い」プログラミングスタイルだと思います。
もちろん、上記は、単なる例として出しているだけ、というのは理解していますが、それでも、この例は「例として不適切」だと考えます。
intに特定するとどういったケースで不都合があるのでしょうか?
現実は理想論だけではすまない、というのをわかった上で、理想論として語れば、
具象型に対してではなくて、インタフェースに対してプログラミングするべき
だからです。
この例で言えば、add
関数は、「+
演算子で加算できる」という性質(インタフェース)を備えた任意のオブジェクトに対して適用可能です。もちろん、個々の具体的な型によって、+
演算子が実行する具体的な処理内容は異なりますが(ポリモーフィズム)、add
関数は、+
演算子という「インタフェース」に対してプログラミングしているわけで、+
演算子の具体的な処理内容は関知していない(というか、+
演算子の具体的な処理内容に依存してはいけない)わけです。
この例で、具象型であるint
に縛るべきではないです。そうしてしまうと、それこそ、後から、int
ではなくfloat
に変えたくなったら、プログラム上のint
というキーワードを全てfloat
に置換しないといけない、みたいな作業が発生することになります。
もっと言えば、add
関数の引数を数値に絞る必然性もないと思います。add
関数の引数は、+
演算子というインタフェースが定義されていればよいわけで、add
関数に、str
やlist
、さらには、__add__
特殊メソッドが定義された独自クラスを入力することは何の問題もないです。もっと正確に言えば、そもそも、add
関数は+
演算子を備える任意のオブジェクトに対してキチンと動作するように書かれているべきです。
実は、最近、静的型付け言語の世界(とくにC++やRustなんかでは顕著ですが)では、可能な限り型指定はしない(コンパイラに自動で型推論させる)、あえて型指定する場合でも最大限Genericな型にする、というプログラミングスタイルが広がっています。
一方で、最近、Pythonで型指定をしているコードをちょくちょく見かけるようになったのですが、なぜこんな「不要な型指定」をするのか、と疑問に思うコードが多かったりします。
正直に言うと、「30年前のC++のコード」を見ているような気分になります。Pythonのプログラマーは、静的型付け言語の世界でのこの30年の試行錯誤(とその結果起ったパラダイムシフト)を、またゼロからやり直すつもりなのか?と思ったり。
これを書くと宗教戦争を引き起こす可能性がかなりありますが、私の「偏見」では、Pythonで型指定したがるのは、Pythonが初めての言語の人たち(あるいは20〜30年前のC++やJavaの知識で止まっている人たち)であって、むしろ、最近、静的型付け言語からPythonに移ってきた人たちは、Pythonで型指定したがらない、という印象があります。