概要
はじめてのPython第3版の勉強メモ
アジェンダ
- 型宣言がないPython
- 共有リファレンス
- 共有リファレンスとオブジェクトの上書き
- 「同等」と「同一」
Pythonのダイナミックな型付け
型宣言がないPython
変数の作成
a = 3
- 変数は値が代入されると同時に作成される
- 作成後に代入が行われた場合、すでに代入されていた値が新しいものに入れ替わる
- この場合、変数はすでに作成済みのため、新たに作成されているわけではない
型情報
- 変数自身は型情報を持たない
- 型情報を持つのは変数に対応する「オブジェクト」
- 変数は対応しているオブジェクト(その時点で代入されているデータ)へのリファレンスだけを持つ
プログラム実行時の変数の扱い
- 対応するオブジェクトにすべて置換えられる
- 対応するオブジェクトがない変数は使用できない
- 変数とオブジェクトはメモリの別の部分に格納されリンクされる
ガーベージコレクション
- 変数に新たなオブジェクトが代入された場合、それまで代入されていたオブジェクトは破棄され、そのオブジェクトが占めていたメモリ領域は開放される、このことをガーベージコレクションと呼ぶ
共有リファレンス
a = 3
b = a
これはいかのようになっている
このように、複数の変数が同じオブジェクトのリファレンスになっている状況を共有リファレンスと呼ぶ
次に、先のコードに1行加える
a = 3
b = a
a = 'spam'
これはこのようになっている
変数aは新たに作られた文字列オブジェクトの'spam'へのリファレンスとなるが、変数bはそのまま、オブジェクト3へのリファレンスのままとなる
共有リファレンスとオブジェクトの上書き
リストは、角カッコの中にオブジェクトを並べたものであり、上書きが可能なオブジェクト
以下の例ではL2は[2, 3, 4]
へのリファレンスのままとなる
L1 = [2, 3, 4]
L2 = L1
L1 = 24
以下の例の場合、リファレンスとなっているオブジェクトの値が上書きされる
# 可変性のオブジェクト
>>> L1 = [2, 3, 4]
# 同じオブジェクトへのリファレンスをもう1つ作る
>>> L2 = L1
# 要素の上書き
>>> L1[0] = 24
# L1に対応するリストに変更が加えられている
>>> L1
[24, 3, 4]
# L2にも影響が!
>>> L2
[24, 3, 4]
以下の方法でコピーさせた場合、L2は変更されず、2つの変数は違うメモリ領域を示している状態となる
# 可変性のオブジェクト
>>> L1 = [2, 3, 4]
# L1のコピーを作る
>>> L2 = L1[:]
# 要素の上書き
>>> L1[0] = 24
# L1に対応するリストに変更が加えられている
>>> L1
[24, 3, 4]
# L2は変更されない
>>> L2
[2, 3, 4]
「同等」と「同一」
>>> x = 42
# 42はすぐに破棄される?
>>> x = 'shrubbery'
Pythonでは、小さい整数や文字数の少ない文字列はキャッシュされて再利用される
オブジェクトが「同じ」であるかどうかの比較には2つの種類がある
- ==演算子は、オブジェクトが「同等」であるかを比較するもの
- is演算子は、オブジェクトが「同一」であるかを比較するためのもの
- 「同等」よりも、「同一」であるための条件の方が厳しい
>>> L = [1, 2, 3]
# MとLは同じオブジェクトのリファレンス
>>> M = L
# 両者が「同等」であるかの比較
>>> L == M
True
# 両者が「同一」であるかの比較
>>> L is M
True
>>> L = [1, 2, 3]
# MとLが対応するオブジェクトは別のもの
>>> M = [1, 2, 3]
# 両者の値は同じ
>>> L == M
True
# 2つのオブジェクトは同等だが同一ではない
>>> L is M
False
同様のことを小さい数値に対して行うと、結果が異なる場合がある
- 下記の場合、XとYは同等ではあっても、同一ではない
- しかし、小さい数値や文字列はキャッシュされて再利用されるため、どちらも同一のオブジェクトのリファレンスになっている
>>> X = 42
# 2つの42は本来、同一でないはず
>>> Y = 42
>>> X == Y
True
# キャッシュが行われるため、2つは同一になる!
>>> X is Y
True