Otsuhachi’s diary

プログラミングのことや覚書などその他いろいろ

当ブログの内容を使用したり参考にした場合に生じた問題の責任は負いかねます。

Python組み込み関数5 -bin・hex・oct編-

Pythonおさらい第5段
制約として公式ドキュメントのみ参照*1として、読む癖をつける訓練も兼ねる。

今回はbin関数oct関数hex関数について。*2

それぞれ整数を2, 8, 16進数表現の文字列に変換する関数である。

今回読み込むドキュメントはこちら[bin, oct, hex]

構成

今回の関数は以下のようになっている。

bin(x)

oct(x)

hex(x)

ドキュメントによると、それぞれ以下のように変換されるらしい。
整数を先頭に特定の文字列をつけた上でn進数表現の文字列に変換する。
結果はPythonの式としても使える形式になる

関数 先頭の文字列 N進数
bin 0b 2
oct 0o 8
hex 0x 16

使ってみる

どういうわけかhexの説明にだけ*3、整数を返す__index__()を定義したら使えるとある。

  1. 正の整数でそれぞれ試す
  2. 負の整数でそれぞれ試す
  3. 自作クラスPersonで以下を試す
    1. __index__()を定義したIdxPersonを定義してそれぞれ試す
    2. __int__()を定義したIntPersonを定義してそれぞれ試す。

実行するコードは以下の通り。

class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def __repr__(self) -> str:
        return f'{self.name}({self.age})'


class IdxPerson(Person):
    def __index__(self):
        return id(self)


class IntPerson(Person):
    def __int__(self):
        return self.age


def show_boh(number):
    print(number)
    print('-' * 70)
    for name, f in zip(('bin', 'oct', 'hex'), (bin, oct, hex)):
        print(f'{name}: {f(number)}')


tests = [
    1930,
    -1930,
    IdxPerson('__index__', 28),
    IntPerson('__int__', 28),
]

for test in tests:
    try:
        show_boh(test)
    finally:
        print()
1930
----------------------------------------------------------------------
bin: 0b11110001010
oct: 0o3612
hex: 0x78a

-1930
----------------------------------------------------------------------
bin: -0b11110001010
oct: -0o3612
hex: -0x78a

__index__(28)
----------------------------------------------------------------------
bin: 0b101010111101010100000100010001111111010000
oct: 0o52752404217720
hex: 0x2af54111fd0

__int__(28)
----------------------------------------------------------------------

Traceback (most recent call last):
...
TypeError: 'IntPerson' object cannot be interpreted as an integer

ドキュメントではhexのみだったが、bin, octでも問題なく__index__()を定義することで使用できるようだ。
整数を返せればいいのかと、__int__()だけ定義したIntPersonではこれらを使用できないこともわかった。

続いてPythonの式として使用してみる。
文字列を返す関数を式に……というのがいまいちピンとこないが、ひとまず以下のコードを実行してみる。

print(bin(18) + bin(10))
0b100100b1010

この結果はシンプルに2つの文字列を連結しただけのようだ。
この時点で勘違いに気付く。

Pythonの式として使える形式というのは、文字が混ざっていても数値として解釈されるということだったらしい。

以下のコードを実行してみる。

print(0b10010 + 0b1010)
print(type(0b10010))
28
int

2進数表現で18+10の計算を行い、その結果を出力しているので、出力は28と正しい値を返した。
また、型名を調べる関数を使用した結果からもint型として扱われているのがわかった。

締め

今回は整数を2, 8, 16進数表現の文字列として取得する方法と、2, 8, 16進数表現でint型を扱う方法が理解できた。
前者はbin, oct, hex関数を使わずにformat関数や文字列に変数を埋め込む書式などでも代用可能らしいが、それらについてはformat関数で触れることにする。覚えていれば

*1:わかりやすく解説している他サイトを見ない

*2:ページタイトルと順番が違うのは、ページタイトルは50音順で表記するため

*3:日本語版ドキュメントでの話なので、英語版ならどれにも書いてあるかもしれない。