
One Point of Python “動的型付け”
Python の初心者向けに、知っておけば得するちょっとした豆知識を提供したい。まず最初に“動的型付け”について取り上げる。
通常のプログラミング言語では、変数の型の宣言が必要なものが多いが、Pythonでは変数の型宣言が不要である。変数は代入と同時に作成される。 例えば、代入文 a = "Diamond" で変数 a が宣言される。ところが、その後に
a = 3.0 を実行しても特に問題は起こらない。それは a には型がないからであ
る。オブジェクトである "Diamond" や 3.0 が型を持っている。そもそも a は
オブジェクトのリファレンスであり、入れ物ではないことによる。リファレンスとは、オブジェクトが記憶されている領域へのポインタのことである。
何が便利か? 型宣言が必要ないので使いたい時に使える。書くべきコードが少なくて済む。また、以下の例に示すように、ポリモーフィズムの基礎をなしている。この例では、演算子+が引数の型で挙動が変わる。
>>> def myplus(a,b):
... return(a+b)
...
>>> myplus(1,2)
3
>>> myplus("Sage", "Math")
'SageMath'
ただ、リファレンスであるがゆえに、注意を要する場合もある。
共有リファレンスの場合には、以下の例が示すように特に問題はない。
>>> a = 33
>>> b = a
>>> b
33
>>> a = 'sage'
>>> b
33
>>> b = 100
>>> a
'sage'
ところが、上書き可能なオブジェクトへの共有リファレンスには、以下の例が示すように、思わぬ書換えが生じてしまうことがある。
>>> l1 = [1, 2, 3]
>>> l2 = l1
>>> l2
[1, 2, 3]
>>> l1[0] = 99
>>> l1
[99, 2, 3]
>>> l2
[99, 2, 3]
>>> l2[2] = 777
>>> l2
[99, 2, 777]
>>> l1
[99, 2, 777]
このような思わぬ書換えを避けたい場合には、コピーを作成しておく必要がある。
>>> l1 = [1, 2, 3]
>>> l2 = l1[:]
>>> l2
[1, 2, 3]
>>> l1[0] = 99
>>> l2
[1, 2, 3]
>>> l2[2] = 777
>>> l1
[99, 2, 3]
さらに、オブジェクトが同等 ( L = M ) と同一 ( L is M ) の違いを理解する必要も生じる。変数がリファレンスであることの慣れが必要である。
>>> L = [7, 8, 9]
>>> M = L
>>> L == M
True
>>> L is M
True
>>> M = [7, 8, 9]
>>> L == M
True
>>> L is M
False