Pythonの演算子について少し意識してみる
意外と面白い公式ドキュメント
最近ヒマなときにPythonの公式ドキュメントを読んだりしているのですが、意外とBuilt-in Typesのページが面白かったりします。(このページです: Built-in Types)
今回はそういったページの中から得られた数値や演算子に関しての小ネタ集です。
Pythonの数値の3つのType
Pythonの数値に関するTypeは先ほどのBuilt-in Typesのページを参照すると3つがあります。
-
int
-
float
-
complex
です。int, floatはそれはそうやろ、という感じですが、complexは意外と知らない人も多い?のではないでしょうか。
実際、 j
または J
を虚数単位としてそのまま記述できます。
>> (1 + 2j) * (1 - 2j) 5
こんな感じですね。
あと、もう一つ知られていない小ネタで、 _
を数字の中に挟んでもOKというのがあります。
>> 2_0_2_4 + 1 2025
実際は3桁区切りとかで使うものだと思いますが、知っておいた上で本当に使いどころで使えると 🆒 かもしれません。
演算子とoperatorモジュール
次は演算子の話です。
Pythonにはoperatorモジュールという標準演算子を関数形式で提供してくれるモジュールがあります。
operator.add(3, 1)
も 3 + 1
も、4を返すわけです。
operator.add
の実装を見るとめちゃくちゃシンプルで、
def add(a, b): "Same as a + b." return a + b
とだけ書いてありました。文字通り標準演算子を関数形式に直しただけ…
ではこの標準演算子ってどうやって計算されているのか?というと、「Pythonのインタプリタで直接処理される」ということになります。
ところで、たまにOSSなどを使っているときに、 +
が明らかに標準の処理と別の働きをしているのを見かけませんか?
演算子のオーバーライド
実は +
のような演算子は自前のクラスでオーバーライドすることが出来ます。
+
をオーバーライドする場合は、 __add__
をクラス内に定義すれば良いです。
たとえば、下記のようなクラスを準備した場合に
class ABCNumber: def __init__(self, value): self.value = value def __add__(self, other): if isinstance(other, ABCNumber): return ABCNumber(self.value - other.value) else: return ABCNumber(self.value + other)
以下のような式をしたらそれぞれ出力がどうなるかわかりますか?
print((ABCNumber(3) + ABCNumber(1)).value) print((ABCNumber(3) + 1).value)
わかりましたか?
こうです。
ABCNumberどうしの +
は実質的にマイナスと処理されます。
(ABCNumber(self.value - other.value)
のほうが返されるので)
このような処理を見て、なるほど…と理解は簡単なのですが、実際に使うタイミングを適切に判断出来るとめちゃくちゃ格好いいですよね。
要するに、
-
頻出する処理で
-
使わないであろう演算子を
このように当ててあげるとよさそうです。
ちなみに、
ABCNumber(3).__add__(1).value
でももちろん
(ABCNumber(3) + 1).value
と同じ結果が得られます。
が、じゃあ、
3.__add__(1)
が出来るかというと、これはできません。
3.
の時点でパーサーはfloatの3.0と判断するんですね。
なので、
3..__add__(1)
ならちゃんと4.0が返ってきます。( 3.0 + 1
と同義)
ではintで処理するにはどうしたらいいかというと、 ()
で区切ってしまえばいいです。
(3).__add__(1)
とすれば良いということになります。非常にややこしいですが面白いですね。
まとめ
今回はPythonの数値に関するリテラルと、演算子のオーバーライドの小ネタでした。
こういうのを正確に答えられたり、オーバーライドを適切な形でズバズバ決められると玄人感が出てきて格好いいですよね。
演算子のオーバーライドなどは実際にどういった形で使っているのか?をまた次回以降で触れられればと思っています。