回答編集履歴

6

修正

2020/08/02 16:44

投稿

kotori_a
kotori_a

スコア705

test CHANGED
@@ -92,17 +92,17 @@
92
92
 
93
93
  以上を総合すると、
94
94
 
95
- 1番目の「*」演算子の使い方(`a =[[0,0,0] for n in range(4)]`)では、異なるリストオブジェクトを4つ作成している(すなわちそれぞれのリストオブジェクトの参照値も異なる)のに対して、
95
+ 1番目のリスト作成(`a =[[0,0,0] for n in range(4)]`)では、異なるリストオブジェクトを4つ作成している(すなわちそれぞれのリストオブジェクトの参照値も異なる)のに対して、
96
96
 
97
- 2番目の「*」演算子の使い方(`[[0] * 3] * 4`)では、
97
+ 2番目の「*」演算子を使ったリスト作成(`[[0] * 3] * 4`)では、
98
98
 
99
- **左に置かれた`[0] * 3`によって作成された1つのリストオブジェクトに対する同一の参照値を4つ繰り返してコピーしているだけ**なので、
99
+ **左に置かれた`[0] * 3`によって作成された1つのリストオブジェクトに対する同一の参照値を繰り返してコピーしているだけ**なので、
100
100
 
101
101
  b[1][1]に値を代入したときの結果が異なるものと推測されます。
102
102
 
103
103
 
104
104
 
105
- 各場合の要素の参照値を検証すると、1番目の場合は参照値が異なりますが、2番目の場合は参照値が4つとも同一であることが確認できます。
105
+ 下記コードのように、各場合の要素の参照値を検証すると、1番目の場合は参照値が異なりますが、2番目の場合は参照値が4つとも同一であることが確認できます。
106
106
 
107
107
  ```
108
108
 

5

修正

2020/08/02 16:44

投稿

kotori_a
kotori_a

スコア705

test CHANGED
@@ -74,17 +74,19 @@
74
74
 
75
75
  とBUILD_LIST は、[0]の作成と[0,0,0]の作成の2回しか呼び出されておらず、1回目になかった「BINARY_MULTIPLY」という命令が見受けられます。つまりキモは多分この「BINARY_MULTIPLY」でしょう。
76
76
 
77
+
78
+
77
79
  pythonコンパイラのソースを探すと、[ここ](https://github.com/python/cpython/blob/master/Python/ceval.c#L1642)を経由して[ここ](https://github.com/python/cpython/blob/master/Objects/abstract.c#L974)で定義されているようです。
80
+
81
+ ここからの中身の詳細は割愛しますが、引数の種類によって、[PyNumberMethods.nb_multiply または PySequenceMethods.sq_repeat のいずれかが呼ばれるらしい](https://stackoverflow.com/a/24703439)です。
78
82
 
79
83
 
80
84
 
81
- 中身を見ると「*」演算子左の引数及び右の引数tp_as_sequence」か否かで処理を分けています。
85
+ そしてリストオブジェクト場合、PySequenceMethods.sq_repeat呼ばれ、最終的に`list_repeat(PyListObject *a, Py_ssize_t n)`([該当箇所](https://github.com/python/cpython/blob/master/Objects/listobject.c#L539))
82
86
 
87
+ が呼ばれているようです。
83
88
 
84
-
85
- tp_as_sequenceは何ぞやというすが[tp_as_sequenceに関するドキュメン](https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_as_sequence)によると、フィルドに関するポインタを格納しているようです。
89
+ の中結局、与えられたリスへの同じ参照値が回数分だけコピされていす。
86
-
87
-
88
90
 
89
91
 
90
92
 

4

修正

2020/08/02 16:40

投稿

kotori_a
kotori_a

スコア705

test CHANGED
@@ -92,7 +92,9 @@
92
92
 
93
93
  1番目の「*」演算子の使い方(`a =[[0,0,0] for n in range(4)]`)では、異なるリストオブジェクトを4つ作成している(すなわちそれぞれのリストオブジェクトの参照値も異なる)のに対して、
94
94
 
95
+ 2番目の「*」演算子の使い方(`[[0] * 3] * 4`)では、
96
+
95
- 2番目の「*」演算子の使い方(`[[0] * 3] * 4`)では、左に置かれた`[0] * 3`によって作成された1つのリストオブジェクトに対する同一の参照値を4つ繰り返してコピーしているだけなので、
97
+ **左に置かれた`[0] * 3`によって作成された1つのリストオブジェクトに対する同一の参照値を4つ繰り返してコピーしているだけ**なので、
96
98
 
97
99
  b[1][1]に値を代入したときの結果が異なるものと推測されます。
98
100
 

3

追記

2020/08/02 16:11

投稿

kotori_a
kotori_a

スコア705

test CHANGED
@@ -32,7 +32,7 @@
32
32
 
33
33
  ```
34
34
 
35
- というようにBUILD_LISTが4回呼び出されています。
35
+ というようにBUILD_LISTがループによって計4回呼び出されています。
36
36
 
37
37
  つまり、新しいリストが4つ作成されています。
38
38
 
@@ -72,7 +72,7 @@
72
72
 
73
73
 
74
74
 
75
- とBUILD_LIST は2回しか呼び出されておらず、1回目になかった「BINARY_MULTIPLY」という命令が見受けられます。つまりキモは多分この「BINARY_MULTIPLY」でしょう。
75
+ とBUILD_LIST は、[0]の作成と[0,0,0]の作成の2回しか呼び出されておらず、1回目になかった「BINARY_MULTIPLY」という命令が見受けられます。つまりキモは多分この「BINARY_MULTIPLY」でしょう。
76
76
 
77
77
  pythonコンパイラのソースを探すと、[ここ](https://github.com/python/cpython/blob/master/Python/ceval.c#L1642)を経由して[ここ](https://github.com/python/cpython/blob/master/Objects/abstract.c#L974)で定義されているようです。
78
78
 
@@ -95,3 +95,61 @@
95
95
  2番目の「*」演算子の使い方(`[[0] * 3] * 4`)では、左に置かれた`[0] * 3`によって作成された1つのリストオブジェクトに対する同一の参照値を4つ繰り返してコピーしているだけなので、
96
96
 
97
97
  b[1][1]に値を代入したときの結果が異なるものと推測されます。
98
+
99
+
100
+
101
+ 各場合の要素の参照値を検証すると、1番目の場合は参照値が異なりますが、2番目の場合は参照値が4つとも同一であることが確認できます。
102
+
103
+ ```
104
+
105
+ a =[[0,0,0] for n in range(4)]
106
+
107
+
108
+
109
+ print(id(a[0]))
110
+
111
+ print(id(a[1]))
112
+
113
+ print(id(a[2]))
114
+
115
+ print(id(a[3]))
116
+
117
+
118
+
119
+ # 出力結果
120
+
121
+ >>> 2458168546376
122
+
123
+ >>> 2458176280200
124
+
125
+ >>> 2458176279624
126
+
127
+ >>> 2458169098184
128
+
129
+
130
+
131
+
132
+
133
+ b = [[0] * 3] * 4
134
+
135
+ print(id(b[0]))
136
+
137
+ print(id(b[1]))
138
+
139
+ print(id(b[2]))
140
+
141
+ print(id(b[3]))
142
+
143
+
144
+
145
+ # 出力結果
146
+
147
+ >>> 1720977937480
148
+
149
+ >>> 1720977937480
150
+
151
+ >>> 1720977937480
152
+
153
+ >>> 1720977937480
154
+
155
+ ```

2

追記

2020/08/02 16:07

投稿

kotori_a
kotori_a

スコア705

test CHANGED
@@ -72,11 +72,9 @@
72
72
 
73
73
 
74
74
 
75
- となっいます。
75
+ BUILD_LIST は2回しか呼び出されておらず、1回目にた「BINARY_MULTIPLY」とう命令が見受けられます。つまりキモは多分この「BINARY_MULTIPLY」でしょう。
76
76
 
77
- キモは多分12行目の「BINARY_MULTIPLY」で、
78
-
79
- これは、pythonコンパイラの[ここ](https://github.com/python/cpython/blob/master/Python/ceval.c#L1642)を経由して[ここ](https://github.com/python/cpython/blob/master/Objects/abstract.c#L974)で定義されているようです。
77
+ pythonコンパイラのソースを探すと、[ここ](https://github.com/python/cpython/blob/master/Python/ceval.c#L1642)を経由して[ここ](https://github.com/python/cpython/blob/master/Objects/abstract.c#L974)で定義されているようです。
80
78
 
81
79
 
82
80
 

1

一部修正

2020/08/02 15:41

投稿

kotori_a
kotori_a

スコア705

test CHANGED
@@ -96,4 +96,4 @@
96
96
 
97
97
  2番目の「*」演算子の使い方(`[[0] * 3] * 4`)では、左に置かれた`[0] * 3`によって作成された1つのリストオブジェクトに対する同一の参照値を4つ繰り返してコピーしているだけなので、
98
98
 
99
- b[1][1]の結果が異なるものと推測されます。
99
+ b[1][1]に値を代入したときの結果が異なるものと推測されます。