演算子と特殊メソッドの関係、数値のメソッドを呼び出してみる

数値演算は学校で習ってきたことなので違和感ないのですが、文字列に対しても `+`, `*`, `%` の演算子を使って演算できます。
`+`と`*`はまだ理解できるけれど、`%`が書式変換として使えるのは驚きました。

```py
>>> 'ABC' + '123'
'ABC123'
>>> 'ABC' * 3
'ABCABCABC'
>>> '%#08x' % 123
'0x00007b'
>>> '%d, %x, %o' % (123, 123, 123)
'123, 7b, 173'
```

pythonはオブジェクト指向スクリプト言語で、文字列が処理メソッドを持っているでしょうから、文字列のメソッド一覧を見てみます。

```py
>>> dir('')    # ''の部分は文字列なら何でもいい
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
```

capitalize から後半は文字列に対する通常メソッドですね。

```py
>>> help(''.capitalize)
Help on built-in function capitalize:

capitalize(...)
    S.capitalize() -> string
    
    Return a copy of the string S with only its first character
    capitalized.

>>> 'ABC'.capitalize()
'Abc'

>>> help(''.center)
Help on built-in function center:

center(...)
    S.center(width[, fillchar]) -> string
    
    Return S centered in a string of length width. Padding is
    done using the specified fill character (default is a space)

>>> 'Python'.center(30, '-')
'------------Python------------'
```

`dir('')`で表示された前半の `__`(下線2つ) で囲まれているのは`特殊メソッド`で、使われ方が決められているメソッドのようです。
`__add__`, `__mul__`, `__mod__` が `+`, `*`, `%` の演算子で呼び出されるメソッドです。

```py
>>> 'ABC'.__add__('123')
'ABC123'
>>> 'ABC'.__mul__(3)
'ABCABCABC'
>>> '%#x'.__mod__(123)
'0x7b'
```

文字列クラスがこれらのメソッドを定義しているおかげで、演算子を使って文字列操作できるわけですね。

では、これはどうでしょう？

```py
>>> 'ABC' + '123' * 3
'ABC123123123'
>>> 'ABC'.__add__('123').__mul__(3)
'ABC123ABC123ABC123'
```

上の式と下の式で結果が違ってしまいました。
演算子には優先順位があり、`+`よりも`*`が優先されるため、Pythonインタープリタは上の式を `'ABC' + ('123' * 3)` と解釈して次のようにメソッドを呼び出しているので結果が違ったわけですね。

```py
>>> 'ABC'.__add__('123'.__mul__(3))
'ABC123123123'
```

ついでに、数値もメソッド呼び出ししてみましょう。

```py
>>> dir(0)  # 0は別の数値でもいい
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
>>> 123.__add__(456)
SyntaxError: invalid syntax
>>> 123 .__add__(456)
579
>>> (123).__add__(456)
579
```

`123.__add__(456)`がシンタックスエラーになってますが、`.`が小数点として解釈されてしまうためです。空白を空けるか括弧で囲むとメソッド呼び出しできます。

ちなみに、ビルトイン関数のlen関数は、`__len__`メソッドを呼び出しているわけですね。
個人的には`length()`メソッドも別名定義してくれればいいのに、とか思ってしまいますが。

```py
>>> len('abcdefg')
7
>>> 'abcdefg'.__len__()
7
```

他にも、比較演算子、配列アクセス、シーケンシャルアクセス、reduce() などに使う特殊メソッドがあるわけですね。