変数への累算代入とオブジェクトへの累算代入の違いを図で理解する
※ 他の方の記事のコメントに書いたのですが、みなさんにも知って欲しくて記事にしました。
オブジェクト(値)と変数
Pythonでは、None、数値、関数、クラス、メソッド、モジュールなど すべて が オブジェクト(何らかのクラスのインスタンス)に 変換 されます。
変数 は オブジェクトへの参照値 である オブジェクトid を 保持 します。どんなオブジェクトでも 代入 できます。違う型のオブジェクトを 再代入 することもできます。
変数 は、変数名 を 辞書キー として、オブジェクトid を 辞書値 として 変数辞書 に格納されます。変数辞書 の内容は、vars
関数, locals
関数, globals
関数で確認できます。
リスト は オブジェクトid の 配列 です。配列要素毎に違う型のオブジェクトを 代入・再代入 することもできます。
変数代入・再代入
>>> id(1)
15812500000
>>> type(1)
<class'int'>
>>> 1 .__class__ # 小数点に解釈されないようにドットの前に空白を入れる
<class'int'>
>>> 1 .real
1
>>> id(2)
15812500032
>>> a = 1
>>> id(a)
15812500000
>>> a = 2
>>> id(a)
15812500032
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class'_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
'a': 2}
変数への累算代入その1:イミュータブルオブジェクトの場合
+=
のような 代入 を 累算代入 といいます。
Pythonの累算代入は、変数に代入されているオブジェクトが イミュータブル(不変)オブジェクト か ミュータブル(可変)オブジェクト かで動作が違います。
int型のようなイミュータブルオブジェクトの場合は、下図のように別オブジェクトを再代入します。
>>> a = 2
>>> id(a)
15812500032
>>> a += 1
>>> id(a)
15812500064
リストオブジェクト
>>> id(1)
15812500000
>>> id(2)
15812500032
>>> id(3)
15812500064
>>> a = [1, 2, 3]
>>> id(a)
123145300973832
>>> type(a)
<class'list'>
>>> a.__class__
<class'list'>
>>> len(a)
3
>>> a.__len__()
3
>>> for ele in a:
... print(ele, type(ele), id(ele))
...
1 <class'int'> 15812500000
2 <class'int'> 15812500032
3 <class'int'> 15812500064
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class'_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>,
'a': [1, 2, 3],
'ele': 3}
オブジェクトへの累算代入
>>> a = [1, 2, 3]
>>> id(a[0])
15812500000
>>> a[0] += 1
>>> id(a[0])
15812500032
>>> id(a[1])
15812500032
なお、-5
~ 256
の整数値(int型オブジェクト)はよく利用される値としてオブジェクトがキャッシュされて 共有再利用 されるため、a[0]
と a[1]
の オブジェクトid が同じになっています。
オブジェクト指向のデザインパターンでいう「flyweightパターン」が使われています。
変数への累算代入その2:ミュータブルオブジェクトの場合
リストはミュータブルオブジェクトのため、int型オブジェクトのときとは動作が異なります。
下図のようにオブジェクトに処理を依頼し、オブジェクト自身がオブジェクト内容を変更します。
>>> a = [1, 2, 3]
>>> id(a)
123145300973832
>>> hasattr(a, '__iadd__')
True
>>> hasattr(2, '__iadd__')
False
>>> a += [4]
>>> id(a)
123145300973832
>>> len(a)
4
>>> a.__len__()
4
>>> id(a[3])
15812500096
参考
累算代入文: https://docs.python.org/ja/3/reference/simple_stmts.html#augmented-assignment-statements
累算代入メソッド: https://docs.python.org/ja/3/reference/datamodel.html#object.__iadd__
Author And Source
この問題について(変数への累算代入とオブジェクトへの累算代入の違いを図で理解する), 我々は、より多くの情報をここで見つけました https://qiita.com/shiracamus/items/50b554cd21a4aa9fc574著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .