Pythonに挑戦(6)その(3)からの続き
(6) ミュータブル、イミュータブル
ミュータブルは変更可能なオブジェクトでリスト、イミュータブルは変更不可能なオブジェクトで、ブール型(bool)、文字列(str)、整数(int)、実数(float)、タプルと言われますが、実際の動作は少々異なります。
id()関数を使って調べると、以下のように、ブール型、文字列、整数では、変数の内容を変更すると、idが変化します。リストでは要素の追加を行っても、idは変化しません。リストの要素を変更すると、要素のidは変化します。リストの要素は、文字列、整数、実数だからです。
つまり、ミュータブルは、変更を行ってもidが変化しないオブジェクトであり、イミュータブルは、変更を行うとidが変化するオブジェクト、と言うことができます。
id()関数を使って調べると、以下のように、ブール型、文字列、整数では、変数の内容を変更すると、idが変化します。リストでは要素の追加を行っても、idは変化しません。リストの要素を変更すると、要素のidは変化します。リストの要素は、文字列、整数、実数だからです。
つまり、ミュータブルは、変更を行ってもidが変化しないオブジェクトであり、イミュータブルは、変更を行うとidが変化するオブジェクト、と言うことができます。
b1 = True
print(“b1のid:“, hex(id(b1)))
b1 = not(b1)
print(“b1のid:“, hex(id(b1)))
j1 = 1
print(“j1のid:“, hex(id(j1)))
j1 = j1 + 2
print(“j1のid:“, hex(id(j1)))
s1 = “test”
print(“s1のid:“, hex(id(s1)))
s1 = s1 + “123”
print(“s1のid:“, hex(id(s1)))
t1 = (‘a’, ‘b’, ‘c’)
print(“t1のid:“, hex(id(t1)))
t1 = (‘d’, ‘e’)
print(“t1のid:“, hex(id(t1)))
e1 = []
print(“e1のid:“, hex(id(e1)))
e1.append(“test1”)
print(“e1のid:“, hex(id(e1)), “, e1[0]のid:“, hex(id(e1[0])))
e1.append(“test2”)
print(“e1のid:“, hex(id(e1)), “, e1[0]のid:“, hex(id(e1[0])), “e1[1]のid:“, hex(id(e1[1])))
e1[0] = “test123”
e1[1] = “a”
print(“e1のid:“, hex(id(e1)), “, e1[0]のid:“, hex(id(e1[0])), “e1[1]のid:“, hex(id(e1[1])))
print(“b1のid:“, hex(id(b1)))
b1 = not(b1)
print(“b1のid:“, hex(id(b1)))
j1 = 1
print(“j1のid:“, hex(id(j1)))
j1 = j1 + 2
print(“j1のid:“, hex(id(j1)))
s1 = “test”
print(“s1のid:“, hex(id(s1)))
s1 = s1 + “123”
print(“s1のid:“, hex(id(s1)))
t1 = (‘a’, ‘b’, ‘c’)
print(“t1のid:“, hex(id(t1)))
t1 = (‘d’, ‘e’)
print(“t1のid:“, hex(id(t1)))
e1 = []
print(“e1のid:“, hex(id(e1)))
e1.append(“test1”)
print(“e1のid:“, hex(id(e1)), “, e1[0]のid:“, hex(id(e1[0])))
e1.append(“test2”)
print(“e1のid:“, hex(id(e1)), “, e1[0]のid:“, hex(id(e1[0])), “e1[1]のid:“, hex(id(e1[1])))
e1[0] = “test123”
e1[1] = “a”
print(“e1のid:“, hex(id(e1)), “, e1[0]のid:“, hex(id(e1[0])), “e1[1]のid:“, hex(id(e1[1])))
とすると、画面に、
b1のid: 0x7ff9f66ea5c0
b1のid: 0x7ff9f66ea5e0
j1のid: 0x7ff9f67ac9b8
j1のid: 0x7ff9f67ac9f8
s1のid: 0x162969fbe10
s1のid: 0x162993decd0
t1のid: 0x1629938d6c0
t1のid: 0x1629937f2c0
e1のid: 0x16299466b80
e1のid: 0x16299466b80 , e1[0]のid: 0x16299381740
e1のid: 0x16299466b80 , e1[0]のid: 0x16299381740 e1[1]のid: 0x16299381770
e1のid: 0x16299466b80 , e1[0]のid: 0x162993817a0 e1[1]のid: 0x7ff9f67b4ce0
b1のid: 0x7ff9f66ea5e0
j1のid: 0x7ff9f67ac9b8
j1のid: 0x7ff9f67ac9f8
s1のid: 0x162969fbe10
s1のid: 0x162993decd0
t1のid: 0x1629938d6c0
t1のid: 0x1629937f2c0
e1のid: 0x16299466b80
e1のid: 0x16299466b80 , e1[0]のid: 0x16299381740
e1のid: 0x16299466b80 , e1[0]のid: 0x16299381740 e1[1]のid: 0x16299381770
e1のid: 0x16299466b80 , e1[0]のid: 0x162993817a0 e1[1]のid: 0x7ff9f67b4ce0
と表示され、idの変化を確認できます。
(7) イテレータ、イテラブル
イテレータは、__next__メソッドを持っており、next()関数を使って、要素を1個ずつ順に取得できるオブジェクトです(というよりも、next()関数は、複数の要素の中から1個を選んで取り出す順番の先頭に置く、という動作をします)。全部の要素を出してしまうと例外が発生します。イテレータitもイテラブルですが、it[1]のように添字をつけて要素にアクセスしようとするとエラーになります。イテレータでは要素が番号付けられて1列に並んでいるわけではなく、あくまでnext()関数を使って次の要素が取り出せるだけです。generatorオブジェクトは内部でyield文が使われていてイテレータです。
イテラブルは、for … in…で繰り返すことができる反復可能オブジェクトですが、繰り返し処理の中でイテレータに変換されています。イテラブルは、__iter__メソッドを持っており、iter()関数でイテレータを生成できます。イテラブルはイテレータではありません。range関数の返すrangeオブジェクトはイテラブルだがイテレータではなく、next()は適用できません。rangeオブジェクトはリストでもありません。enumerate()関数は、イテラブルを引数として、イテレータを返す関数です。文字列、リスト、タプル、辞書、mapオブジェクト、fileオブジェクトはイテラブルです。
イテラブルは、for … in…で繰り返すことができる反復可能オブジェクトですが、繰り返し処理の中でイテレータに変換されています。イテラブルは、__iter__メソッドを持っており、iter()関数でイテレータを生成できます。イテラブルはイテレータではありません。range関数の返すrangeオブジェクトはイテラブルだがイテレータではなく、next()は適用できません。rangeオブジェクトはリストでもありません。enumerate()関数は、イテラブルを引数として、イテレータを返す関数です。文字列、リスト、タプル、辞書、mapオブジェクト、fileオブジェクトはイテラブルです。