20

Pythonセットの要素が順序付けられていないことを理解しています。popメソッドを呼び出すと、任意の要素が返されます。私はそれで大丈夫です。

私が疑問に思っているのは、セットが同じ履歴を持っている場合、popが常に同じ要素を返すかどうかです。もちろん、Pythonの1つのバージョン内では、Pythonのさまざまなバージョン/実装が独自のことを行ってもかまいません。特に、Python2.7について質問しています。この場合、APIよりも実装の問題です。

私はゲームの手続き型ダンジョンジェネレーターでセットを頻繁に使用していますが、特定のシードに対して結果が決定論的であるようにしたいと思います。

4

5 に答える 5

30

一般的に答えはノーです。@Christopheと@Marcin(un)が役立つPythonソースは、要素がハッシュテーブルに表示される順序でポップされることを示しています。したがって、ポップ順序(およびおそらく反復順序)は決定論的ですが、固定ハッシュ値に対してのみです。のドキュメントのによると、これは数字には当てはまりますが、文字列には当てはまりません。これは、偶然にもあなたの質問に直接触れています。__hash__

デフォルトでは、str、bytes、およびdatetimeオブジェクトのハッシュ()値は、予測できないランダムな値で「ソルト」されていることに注意してください。それらは個々のPythonプロセス内で一定のままですが、Pythonを繰り返し呼び出す間で予測することはできません。

[...]

ハッシュ値を変更すると、dict、set、およびその他のマッピングの反復順序に影響します。Pythonは、この順序について保証していません(通常、32ビットビルドと64ビットビルドの間で異なります)。

編集: @Marcinが指摘しているように、私が引用したリンクはPython2には適用されません。Python3.3ではハッシュのランダム化がデフォルトになりました。Python 2.7には、デフォルトで意図的に非決定論的な文字列ハッシュがありません。

一般に、これは、ハッシュがその値の反復可能な関数ではないオブジェクトの場合に問題になります(たとえば、ハッシュがメモリアドレスに基づいている場合)。ただし、逆に、__hash__セット内のオブジェクトに対して独自のメソッドを定義すると、再現可能な順序でオブジェクトが返されることが期待できます。(セットの履歴とプラットフォームが固定されている場合)。

于 2012-05-03T13:51:58.090 に答える
6

内部的には、状況はに似ていると思いますdict。順序はハッシュアルゴリズムによって決定され、状況によっては同じ結果が得られます。ただし、これに依存しないでください。要素の数が増えると、セットで衝突(つまり、内部ハッシュ)が発生し、最終的には異なる順序になります。

要するに:いいえ、set.pop()決定論的ではありません。APIが明示的に述べているので、順序を想定しないでください。

セットオブジェクトは順序付けられていないコレクションです

于 2012-05-03T13:13:25.380 に答える
4

ドキュメントには、決定論的でなければならないことが指定されていないため、そうではないと想定する必要があります。

于 2012-05-03T13:09:03.067 に答える
2

決定論を強制したい場合は、次のようなことを試すことができます

value = min(my_set)
my_set.remove(value)
于 2012-05-03T13:33:22.000 に答える
-1

本当にPythonの特定のバージョンをターゲットにしている場合は、ソースを調べてその動作をテストできます(ただし、十分にテストしてください。負荷率などを考慮してください)。

移植性が必要な場合、またはset必要に応じて機能しない場合は、ordereddictを使用してください(ここにあります:http://code.activestate.com/recipes/576693/ ;他にもたくさんあるので、見た目が好きなものを見つけてくださいの)、そしてそれをセットとして適応させます。

更新:順序付けられたセットは次のとおりです:http://packages.python.org/Brownie/api/datastructures.html#brownie.datastructures.OrderedSet

于 2012-05-03T13:40:06.980 に答える