pathlibって便利ですよね
最近pathlibの便利さが様々なところで語られています。
pathlibの様々な機能は上記の記事やドキュメントを読んでいただければわかるので、今日はその1つに、Pythonのオーバーロードを説明するのに良い機能があるので紹介したいと思います。
pathlibはこんな風にパスを書けます。
from pathlib import Path etc_dir = Path('/etc') init_dir = 'init.d' print(etc_dir/init_dir/'reboot') # => /etc/init.d/reboot
最初に見ると、ちょっとギョッとするのではないでしょうか?
pathlibでは上記のように、1 / 2 #=> 0.5
のように 変数 / 変数
という書き方でパスを書くことができます。慣れてくるとLinuxのパスを普通に書いているような気持ちで書けるので気持ち良いです。本来は除算の演算子である /
でどうしてこんな風に書けるのでしょうか?答えはソースを読むとわかります。
https://github.com/python/cpython/blob/3.6/Lib/pathlib.py#L898
def __truediv__(self, key): return self._make_child((key,))
この __truediv__
メソッドが答えです。
Pythonは演算子をオーバーロードできる
公式ドキュメントの 「3. Data model」を読むとPythonの演算子をオーバーロードできることがわかります。
3. Data model — Python 3.7.3 documentation
The following methods can be defined to emulate numeric objects. Methods corresponding to operations that are not supported by the particular kind of number implemented (e.g., bitwise operations for non-integral numbers) should be left undefined.
object.__add__(self, other) object.__sub__(self, other) object.__mul__(self, other) object.__matmul__(self, other) object.__truediv__(self, other) ...
これで +
や -
、 /
といった演算子を再定義できます。それではこの機能を使って擬似的にpathlibを実装してみると次のようになります。
class myPath(): def __init__(self, path): self._path = path def __truediv__(self, add_path): self._path = self._path + '/' + add_path return self def __str__(self): return self._path etc_dir = myPath('/etc') init_dir = 'init.d' print(etc_dir / init_dir / 'reboot') # => /etc/init.d/reboot
無事、pathlibと同様の挙動が実装できました。 pathlibは演算子オーバーロードをとても上手く使った実装だと思います
他にも演算子オーバーロードはこんなところでも
pathlib以外で自分が良く使う演算子オーバーロードはnumpyの @
です。これを使うと機械学習の実装では欠かすことのできないドット積(内積)の計算を行うことができます。元々は dot
メソッドを呼び出さなければいけなかったのですが、途中で演算子オーバーロードとして実装されたので簡単に書けるようになりました。
import numpy as np a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(a * b) # [[ 1 4 9] # [16 25 36] # [49 64 81]] # 前は dot メソッドを呼び出す必要があった print(a.dot(b)) # [[ 30 36 42] # [ 66 81 96] # [102 126 150]] # 今は@演算子でdot積が計算できる print(a @ b) # [[ 30 36 42] # [ 66 81 96] # [102 126 150]]
演算子オーバーロード、とても便利ですね。
最後に
- この記事を書いていている最中に知ったのですが、C++ でも最近、同様の演算子オーバーロードが導入されたようです。 std::filesystem::path - cppreference.com
- 最初に発明した人は誰なのでしょうか?頭良いな〜と思いました。
- 演算子オーバーロードの詳しい説明や活用方法は「Fluent Python」に丁寧に書いてあるのでさらに知りたい方はオススメです
Fluent Python ―Pythonicな思考とコーディング手法
- 作者: Luciano Ramalho,豊沢聡,桑井博之,梶原玲子
- 出版社/メーカー: オライリージャパン
- 発売日: 2017/10/07
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る