3

だから私はPythonでゲームを書いています、そして私が解決しようとしている問題は私が2Dリスト(つまりリストのリスト)を1Dリストに変えることを必要とします。これを行う方法をいくつか見てきましたが、それらのいずれかが、内部に保持されているオブジェクトのコピーを作成するのか、それとも新しい参照だけを作成するのかはわかりません。正直なところ、Python標準ライブラリは、オブジェクト/シーケンスがコピーされているのか、単に参照で埋められているのかが常に明確であるとは限らないという点で私を混乱させます。

これらは私の特定の状況についての仮定です。

  • 私の2Dリストは、マトリックスとして表されている場合、完全に長方形であると想定できます。
  • 上記の仮定が当てはまらない解決策があればいいのですが、現時点では必須ではありません。
  • 3D+リストについて心配する必要はありません。

ありがとう!

4

4 に答える 4

7

ご覧になったすべての方法についてお話しすることはできませんが、一般に、Python のオブジェクト セマンティクスにより、コピーは作成されません。

>>> a = [[1,2.3,'3', object()], [None, [2,3], 4j]]
>>> b = [v for row in a for v in row]
>>> a
[[1, 2.3, '3', <object object at 0x1002af090>], [None, [2, 3], 4j]]
>>> b
[1, 2.3, '3', <object object at 0x1002af090>, None, [2, 3], 4j]
>>> [id(obj) for row in a for obj in row]
[4298185464, 4298195480, 4299558664, 4297781392, 4296523616, 4299692656, 4297773296]
>>> [id(obj) for obj in b]
[4298185464, 4298195480, 4299558664, 4297781392, 4296523616, 4299692656, 4297773296]

これvは、「に等しい新しいオブジェクト」という意味ではなくv、単にv、オブジェクト自体を意味します。

于 2012-08-26T19:22:46.630 に答える
1

おそらく、Pythonドキュメントのこの部分は、Pythonが何をするのかを理解するのに役立ちます。

オブジェクトを「所有」する人は誰もいません。ただし、オブジェクトへの参照を所有することはできます。オブジェクトの参照カウントは、オブジェクトへの所有参照の数として定義されるようになりました。参照の所有者は、参照が不要になったときにPy_DECREF()を呼び出す責任があります。参照の所有権を譲渡することができます。所有されている参照を破棄するには、3つの方法があります。それを渡すか、保存するか、Py_DECREF()を呼び出します。所有されている参照を破棄するのを忘れると、メモリリークが発生します。

さて、これはCコードからのPythonオブジェクトの使用を指しますが、インタープリターがこれを正確に行うので、オブジェクトと参照がPythonでどのように管理されているかを理解できます。

「誰もオブジェクトを所有していない」ので、アイテムをリストに入れると、このリストはアイテムをコピーせ、単に参照を所有します。実際には、ポインタをコピーして参照カウントをインクリメントします(また、置き換えられた他のオブジェクトもデクリメントします)。

Pythonの観点からは、オブジェクトにアクセスすることはできませんが、オブジェクトへの参照のみにアクセスできます。変数に入れることができるものはすべて、実際にはオブジェクトへの参照です。したがって[1,2].append(3)、3をコピーするのではなく、単に参照をコピーします。

オブジェクトをコピーする場合は、copyモジュールを使用する必要があります。または、一部のタイプでは、オブジェクトを引数としてクラスを呼び出します(たとえばint(1234)、Pythonが-からの整数を小さな配列に格納している場合でも、「1234」のコピーを作成します5〜256の小さな文字列なので、int(42)「42」はコピーされません)

于 2012-08-26T19:42:29.100 に答える
1

コピー/参照に関するあなたの質問に関して、Pythonはさまざまな方法で可変/不変変数を操作します.不変変数(int、float、string、tuplesなど)の場合はコピーを取得し、可変(その他すべて)の場合-「参照」を取得します。

Python リストの平坦化について:itertoolsモジュールを見てください。次のようなことができます。

>>> from itertools import chain
>>> chain(*[[1,2,3], [4,5,6], [7,8,9]])
<itertools.chain object at 0x104ff5110>
>>> list(_)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
于 2012-08-26T19:24:30.700 に答える
0

次のようなことができます:

arr2d = [[1,2,3],[4,5,6],[7,8,9]]
arr1d = []
for x in arr2d:
   arr1d.extend(x)

これはコピーを作成せず、1 次元配列を変更しますが、反映されません。将来の参照のために、コピーされていないことを確認したい場合は、copyモジュールをインポートしてcopy.deepcopy(array)、単にの代わりに使用arrayすると安全です。

于 2012-08-26T19:29:22.627 に答える