Python簡単実験:オブジェクトのIDの調査


2016年 12月 06日

前回、

B = [[]]*6

による繰り返しは、結局同じものを指していたのだが、実際に値を入れて変になることで確認した。

今回は、もっと便利な、明白な方法で調べる。

Pythonは何でもオブジェクトにしてしまう。本当に何でもなのだ。それをちょっとだけ実験する。

id(オブジェクト)なる関数があり、引数に何でも良いから入れると、そのオブジェクトID(識別子)を返してくる。
これを使って、調べてみよう。

In [4]: B = [[]]*6

In [5]: print("%0x\n%0x\n%0x"%(id(B[0]),id(B[1]),id(B[5])))
7f7817d2e5c8
7f7817d2e5c8
7f7817d2e5c8

まったく同じIDなので、[]のオブジェクトは1つしか無いことが分かった。

Pythonのオブジェクト、とくにリストは、リストの中にリストを自由に入れられ、複雑な構造も表現できる。
しかし、こういうオブジェクトをちゃんとコピーすることを考えよう。

Pythonでオブジェクトをコピーする方法がいくつかあるので、その比較実験を行ってみる。

import copy

A = [1,[2,[3,[4]]]]
B = A
C = A.copy()
D = copy.copy(A)
E = copy.deepcopy(C)

これで、元のオブジェクトAと、色々な方法でコピーしたB,C,D,Eが揃った。

==で等しいかどうかチェックしてみた。

In [29]: A==B,B==C,C==D,D==E
Out[29]: (True, True, True, True)

同じである。

といっても、これは見かけだけの可能性があるので、IDを調べよう。

In [30]: print("%0x\n%0x\n%x\n%x\n%x\n"%(id(A),id(B),id(C),id(D),id(E)))
7f78179aeb08
7f78179aeb08
7f78179b4608
7f78179b0fc8
7f78179efc08

AとBは全く同じであり、C,D,Eはそれぞれ別のオブジェクトである。

In [31]: print("%0x\n%0x\n%x\n%x\n"%(id(A[1]),id(C[1]),id(D[1]),id(E[1])))
7f78179efa48
7f78179efa48
7f78179efa48
7f78179efd48

deepcopyしたEだけが異なることが分かった。つまり、ちゃんとコピーしたいときには、deepcopyしないとダメである。

次に、リストの最初の要素のIDを調べた。

In [32]: print("%0x\n%0x\n%x\n%x\n"%(id(A[0]),id(C[0]),id(D[0]),id(E[0])))
7f7835ba5a20
7f7835ba5a20
7f7835ba5a20
7f7835ba5a20

全部同じである。
リストの最初の要素はただの数字、整数の1であった。

ということは、整数さえもオブジェクトなのだろうか?