Edited at

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

More than 3 years have passed since last update.

数値演算は学校で習ってきたことなので違和感ないのですが、文字列に対しても +, *, % の演算子を使って演算できます。

+*はまだ理解できるけれど、%が書式変換として使えるのは驚きました。

>>> 'ABC' + '123'

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

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

>>> 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 から後半は文字列に対する通常メソッドですね。

>>> 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__+, *, % の演算子で呼び出されるメソッドです。

>>> 'ABC'.__add__('123')

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

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

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

>>> 'ABC' + '123' * 3

'ABC123123123'
>>> 'ABC'.__add__('123').__mul__(3)
'ABC123ABC123ABC123'

上の式と下の式で結果が違ってしまいました。

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

>>> 'ABC'.__add__('123'.__mul__(3))

'ABC123123123'

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

>>> 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()メソッドも別名定義してくれればいいのに、とか思ってしまいますが。

>>> len('abcdefg')

7
>>> 'abcdefg'.__len__()
7

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