]> Panopticon :: Python :: Pythonの多次元リストをどのように作るべきか

<< PILのImageFilter | main | さようなら >>

Pythonの多次元リストをどのように作るべきか

Pythonで多次元リストを作るときに、どうすれば見栄えがよいか、ということを小一時間考えていました。

一次元の簡単なリストであれば、

>>> map(lambda x: 0, range(5))
[0, 0, 0, 0, 0]
>>> [0]*5
[0, 0, 0, 0, 0]

[0]*5は非常に簡単でいいのですが、参照「先」に対する操作を行うときには少し気を付ける必要があります。この方法で生成されたリストの要素は、すべて同じインスタンスを指しているからです。

>>> a = [[]]*5
>>> a
[[], [], [], [], []]
>>> a[1].append(1)
>>> a
[[1], [1], [1], [1], [1]]

したがって、この記法で多次元リストを作ることはできません。多次元リストのようなものはできますが、多次元リストとして使うことはできません。すべての行が、ただ一つの実体を参照しているからです。

>>> a = [[0]*3]*2
>>> a
[[0, 0, 0], [0, 0, 0]]
>>> a[1][1] = 3
>>> a
[[0, 3, 0], [0, 3, 0]]

こんなときは、おそらくリスト内包表記を使うのが一番簡単だと思います。ただ、これは次元が増えると大変です。入れ子となった内包表記を全て一行におさめる必要があるからです。

>>> a = [ [ [] for j in range(0,3) ] for i in range(0,2) ]
>>> a
[[[], [], []], [[], [], []]]
>>> a[1][1] = 3
>>> a
[[[], [], []], [[], 3, []]]

結局、考えていたことというのは、次元が増えたときにはdeepcopy()を使うしかないのか?ということです。何か代替があってもよさそうな気がするんですが。

import copy

def hyperlist(dimension=(), baselist=[]):
   if dimension:
      return hyperlist(dimension[1:], [ copy.deepcopy(baselist) for i in range(0, dimension[0]) ])
   else:
      return baselist

# dimension : dimensions (x, y, z, ...)
# beselist : Initial Entity (You can use it individually)
>>> a = hyperlist((4,3,2))
>>> a
[[[[], [], [], []], [[], [], [], []], [[], [], [], []]],
 [[[], [], [], []], [[], [], [], []], [[], [], [], []]]]
>>> a[1][1][1].append(3)
>>> a
[[[[], [], [], []], [[], [], [], []], [[], [], [], []]],
 [[[], [], [], []], [[], [3], [], []], [[], [], [], []]]]
>>> a[1][2][2] = 4
>>> a
[[[[], [], [], []], [[], [], [], []], [[], [], [], []]],
 [[[], [], [], []], [[], [3], [], []], [[], [], 4, []]]]
>>> a[0][0][0].append([1,2])
>>> a
[[[[[1, 2]], [], [], []], [[], [], [], []], [[], [], [], []]],
 [[[], [], [], []], [[], [3], [], []], [[], [], 4, []]]]
カテゴリ

Trackback URI

http://www.panopticon.jp/mt/mt-tb.cgi/103

Trackbacks(1)

[Python]巡回 from 常山日記

svn for win32コマンドの文字化け対策でpysvn落ちる Pythonで全角から半角への変換 Cygwin SQLAlchemy Instal... [続きを読む]

コメントする