Pythonの型の分類と代入
変数が指すオブジェクトがどれかなどの振る舞いをすぐ忘れてしまうのでメモしておく。
組み込み型の分類
まず、Pythonの組み込み型についてまとめておく。
管理方式
管理方式の違いで分類すると、以下のようになる。
- コレクション型(=コンテナ型):複数のデータをまとめたもの
+ シーケンス型:要素を順番に並べて管理。整数のindexでデータを管理できる。
例)文字列、リスト、タプル
+ マップ型:キーと値のペアで要素を管理。
例)ディクショナリ
- 非コレクション
例)数値型(int, float, long, complex)、ブール型、None
文字型がシーケンス型なのは面白い。シーケンスなので、たとえば、
a = "oppai" print a[4] #i
のようにスライスを使って、要素の指定とかができる。
変更可能性
変更可能性で分類すると、以下のようになる。
- 変更可能 (mutable)
例)リスト、ディクショナリ
- 変更不能 (immutable)
例)数値型、文字列、タプル
基本的に、代入なりなんなりをした時の挙動は、変更可能かどうかで決まる。
オブジェクトはメモリに保存されているが、変更可能ならば、そのメモリに書かれているオブジェクトは書き換え可能になる。
代入の挙動
変更可能な型の場合:
x = [1, 2] print 'x =', id(x) y = [1, 2] print 'y =', id(y) print x == y print x is y y = x print 'y =', id(y) print x == y print x is y
x = 4339028480
y = 4339029056
True
False
y = 4339028480
True
True
変数は「=」の左辺において、
x = [1, 2]
とすると、変数xがオブジェクト[1,2](リスト)を指すようになる。
一方、右辺に置くと、変数xが指す(参照する)オブジェクトを表す。
関数idはそのオブジェクトのメモリ上のアドレスを返す。
関数isは同じアドレスの同一のオブジェクトかどうかを調べる。
==は値を比べる(idでオブジェクトのアドレスを調べられるので、x is yはid(x)==id(y)と同じもの)。
上の例では、最初にyに代入した[1,2]はxのものとは別のオブジェクトなので、==では一致するが、isでは別物になる。
一方、y=x とすると、変数yも変数xと同じオブジェクトを参照するようになるので、isで一致する。
変更不可能な型の場合:
x = "oppai" print 'x =', id(x) y = "oppai" print 'y =', id(y) print x == y print x is y
x = 4300154512
y = 4300154512
True
True
このように文字列は、別々に作ったはずの変数が同じオブジェクトを指すことがある。
これは同一のオブジェクトを再利用するため(文字列は変更できないので、こういう仕様でも問題は生じない)。
immutableな数値型も同じ動きをする。
タプルもimmutableだが、なぜか再利用はせず、別のオブジェクトを作る。
(なぜ、こういう仕様なのかは不明。)
一方、リストなどのmutableなものは別に作ったものは別のオブジェクト。
(そうでないと、一方を書き換えると、もう一方も書き換わってしまう。)
もちろん、NumpyのNdarrayも変更可能なので、リストと同じように振る舞う。