Help us understand the problem. What is going on with this article?

Pythonの変数とオブジェクトについて

More than 3 years have passed since last update.

■ 変数について

プログラム言語では、変数とは、なんらかの値を格納する領域です。Pythonの場合、使用する前に変数を宣言する必要はありません。変数に値を代入した時点で、領域が用意されます。
Pythonのようなオブジェクト指向言語では、変数に値そのものが格納されるのではなく、変数の値を指し示す「リファレンス」が格納されると考えるとよいでしょう。

>>> name1 = "山田一郎"

◎図 n1
n1.png

あるいは、「変数名」は値に設定されたタグのようなイメージでとらえてもかまいません。

◎図 n2
n2.png

次のように、変数を別の変数に代入した場合には、同じ値を指し示すようになります。

>>> name1 = "山田一郎"
>>> name2 = name1

◎図 n3
n3.png

■ id()関数でオブジェクトのIDを調べる

Pythonでは数値や文字列を含め、すべての値はオブジェクトです。オブジェクトのID(識別値)を調べるにはid()関数を使用します。変数名を引数にid()関数を実行すると参照しているオブジェクトのIDを表示します。前述の例で変数name1とname2のIDをid()関数で調べると、同じIDのオブジェクトを参照していることがわかります。

>>> name1 = "山田一郎"
>>> name2 = name1
>>> id(name1)
4339005200  ←IDが同じ
>>> id(name2)
4339005200  ←IDが同じ

■ 変数に値を再代入した場合

変数に別の値を再代入した場合にはどうでしょう?次の例では、まず、①で変数numに10を代入し、②で変数numの値に「1」を加えて、変数numに代入しています。

>>> num = 10    ←①
>>> num = num + 1   ←②

この場合、②で値が「11」の新たなオブジェクトが生成され、そのリファレンスが変数numに格納されます。つまり①と②では変数numは異なるオブジェクトを指し示しています。
このことはid()関数を使用して確かめられます。

>>> num = 10
>>> id(num)
4297538176
>>> num = num + 1
>>> id(num)
4297538208  ←IDが変化した(参照先が変更された)

■ ミュータブルな値とイミュータブルな値

Pythonのデータ型は、後から値を変更可能な「ミュータブル」な型と、変更出来ない「イミュータブル」に大別されます。

ミュータブル リスト、ディクショナリ、セット,....
イミュータブル 文字列、数値、タプル, ...

Pythonでは文字列や数値といった基本的なデータ型もイミュータブル、つまり後から変更出来ない型です。
さて、前述の例では変数numの値に1を足して、変数numに再代入していました。

>>> num = 10        ←①
>>> num = num + 1   ←②

これは一見、変数numの値を変更しているように見えるので、数値型はミュータブルな型なのでは?と思うかもしれませんが、実はそうではありません。id()関数の実行結果を見るとわかるように、①と②では、変数numは異なる値を指し示しているのです。

■ リストはミュータブル、タプルはイミュータブル

さて、Pythonでは「リスト」はミュータブル、つまり後から値を変更可能な型です。次の例では、3つの整数を要素とするリスト「ages」を生成し、3番目の要素を変更しています。

>>> ages = [1, 2, 3]
>>> ages[2] = 4
>>> ages
[1, 2, 4]

id()関数で調べると、当然のことながら要素の値を変更後もIDは変化していません。

>>> ages = [1, 2, 3]
>>> id(ages)
4338960072
>>> ages[2] = 4
>>> id(ages)
4338960072  ←IDは同じ

それに対してタプルはイミュータブルな型です。要素の値を変更しようとするとエラーになります。

>>> nums = (1, 2, 3)
>>> nums[0] = 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

■ 文字列もイミュータブル

文字列もイミュータブルな型です。したがって、次のように内部の文字を変更しようとするとエラーになります。

>>> str = "abc"
>>> str[1] = "d" # 2文字めに「"d"」を代入
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

誤解しやすい例として、次の例を見てみましょう。

>>> str = "abc"
>>> str = str + "bcd" # strと"bcd"を連結してstrに再代入 ←①
>>> str
'abcbcd'

この例では、①で変数strと文字列「"bcd"」を連結しているため、文字列が変更されたように見えますが、そうではありません。①で新たな文字列「"abcbcd"」が生成され、そのリファレンスが変数strに格納されるのです。
id()関数で調べると①の後でIDが変更されていることが確認できます。

>>> str = "abc"
>>> id(str)
4301952704
>>> str = str + "bcd"
>>> id(str)
4339056968  ←IDが変化した
>>> str
'abcbcd'
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away