Python
 Computer >> コンピューター >  >> プログラミング >> Python

【Python】2次元配列(2Dリスト)を正しい方法で使うには


Pythonには2次元リスト(配列)を作成する方法がいくつかあります。しかし、それぞれの方法の違いを正しく理解していないと、コードに深刻なバグが混入し、原因の特定が非常に難しくなることがあります。

問題のある初期化方法と正しい初期化方法

以下の例では、同じ5×5の2次元リストを2通りの方法で作成し、それぞれ1行目1列目の要素を「1」に変更した結果を表示しています。

rows, cols = (5, 5)
arr = [[0]*cols]*rows
# 1行目の最初の要素を1に変更して配列を表示
arr[0][0] = 1
for row in arr:
   print(row)

arr = [[0 for i in range(cols)] for j in range(rows)]
# 新しい配列でも同様に、1行目の最初の要素を1に変更して表示
arr[0][0] = 1
for row in arr:
   print(row)

出力結果

[1, 0, 0, 0, 0]
[1, 0, 0, 0, 0]
[1, 0, 0, 0, 0]
[1, 0, 0, 0, 0]
[1, 0, 0, 0, 0]
[1, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]

なぜこのような違いが生じるのか

最初の方法 [[0]*cols]*rows では、同じ内側のリストオブジェクトへの参照が rows 回繰り返されています。つまり、すべての行が同一のリストを共有しているため、arr[0][0] = 1 と1か所だけ変更したつもりでも、すべての行の先頭要素が同時に書き換えられてしまうのです。

一方、リスト内包表記を使った2番目の方法では、行ごとに新しいリストオブジェクトが生成されます。そのため、ある行の要素を変更しても他の行には影響せず、直感どおりの動作になります。

まとめ

2次元リストを初期化するときは、乗算による [[0]*cols]*rows のような書き方は避け、リスト内包表記 [[0 for i in range(cols)] for j in range(rows)] を使うのが安全です。「Pythonのリストは参照型である」という特性を理解しておくことが、予期しないバグを防ぐための鍵となります。

  1. Pythonのpydocモジュールを使ったドキュメント生成の完全ガイド

    はじめにpydocモジュールは、Pythonモジュールから自動的にドキュメントを生成するための標準ライブラリです。生成されたドキュメントは、コンソール上にテキストとして表示できるだけでなく、Webブラウザでの閲覧やHTMLファイルとしての保存にも対応しています。この記事では、さまざまな場面でドキュメントを確認する方法を解説するとともに、自分のPythonスクリプト用のドキュメントを作成する際に役立つdocstring(ドキュメンテーション文字列)についても詳しく学びます。それでは、pydocの具体的な使い方を見ていきましょう。準備:pydocのインポートpydocモジュールはPythonに最初

  2. Pythonで作るボールキャッチゲーム|tkinterを使ったシンプルなゲーム開発入門

    Pythonはデータ分析やWeb開発だけでなく、コンピューターゲームの作成にも活用できます。本記事では、Pythonを使って「ボールキャッチゲーム」を作成する方法を解説します。このゲームでは、キャンバスウィンドウの上部からボールが次々と落下し、ウィンドウ下部には移動可能なバーが配置されています。マウスでボタンをクリックしてバーを左右に動かし、落ちてくるボールを受け止めるというシンプルながら楽しいゲームです。ボールは毎回異なる位置から落下するため、反射神経も試されます。実装のアプローチこのゲームを構築するための手順は、以下のステップに沿って進めます。ステップ1 − tkinterで長方形のキャン