Home >Backend Development >Python Tutorial >python 用list of lists表示矩阵的问题?
题主刷leetCode的时候发现的一个小情况>_
python 初始化 a list of lists of integer,就用了如下方式(假设是4 x 4的方阵):
n = 4
matrix = [[0]*n]*n
print matrix
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
然后诡异的是,假如我只想给第二行的中间两个元素赋值:
matrix[1][1:3] = [1, 2]
结果会是:
print matrix
[[0, 1, 2, 0], [0, 1, 2, 0], [0, 1, 2, 0], [0, 1, 2, 0]]
但是如果用如下方式初始化matrix:
matrix = [[0 for col in range(n)] for row in range(n)]
matrix[1][1:3] = [1, 2]
print matrix
[[0, 0, 0, 0], [0, 1, 2, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
会是我想要的答案。
但是不知道第一种初始化方式错在哪里...
<code class="language-text">matrix = [[0]*n]*n
</code>
<code class="language-python"><span class="c">#!/usr/bin/python</span>
<span class="c">#encoding=utf-8</span>
<span class="c"># 内容来自python cookbook 第二版 第4.5章节</span>
<span class="c"># 在无须共享引用的条件下创建列表的列表</span>
<span class="c"># 避免隐式的引用共享</span>
<span class="n">multi</span> <span class="o">=</span> <span class="p">[</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">5</span> <span class="p">]</span> <span class="o">*</span> <span class="mi">3</span>
<span class="k">print</span> <span class="n">multi</span>
<span class="n">multi</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'oops'</span>
<span class="k">print</span> <span class="n">multi</span>
<span class="c"># [ [ 'oops', 0, 0, 0, 0 ],[ 'oops', 0, 0, 0, 0],[ 'oops', 0, 0, 0, 0 ] ] </span>
<span class="c"># 等价方式</span>
<span class="n">row</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">5</span> <span class="c"># row 列表中的5个子项都是引用0</span>
<span class="n">multi</span> <span class="o">=</span> <span class="n">row</span> <span class="o">*</span> <span class="mi">3</span> <span class="c"># multi 列表中的3个子项都是引用row</span>
<span class="c"># 解释: 在row创建中, 有无引用被复制完全不重要, 因为被引用的</span>
<span class="c"># 是数字, 而数字不可改变,换句话说,如果对象是不可改变的,则</span>
<span class="c"># 对象和对对象的引用实际没有区别。</span>
<span class="c"># multi创建中,包含了3个对[row] 内容引用,而其内容则是对一个</span>
<span class="c"># 列表的引用。因此修改时候其他3个引用也改变了,甚至row也改变</span>
<span class="c"># 解决方法:</span>
<span class="n">multilist_method1</span> <span class="o">=</span> <span class="p">[</span> <span class="p">[</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">col</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="p">]</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="p">]</span>
<span class="n">multilist_method2</span> <span class="o">=</span> <span class="p">[</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">5</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="p">]</span>
<span class="n">multilist_method1</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'abc'</span>
<span class="n">multilist_method2</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'edf'</span>
<span class="k">print</span> <span class="n">multilist_method1</span>
<span class="k">print</span> <span class="n">multilist_method2</span>
</code>
赞同楼上,另外要处理矩阵相关的话用 NumPy
第一种是浅拷贝
这个问题,在《Python cookbook》第二版p148页提到,即隐式的引用共享问题。