6

基本的に、次のようなリストがあり[START, 'foo', 'bar', 'spam', eggs', END]ます。後で比較できるように、START/END識別子は後で必要になります。今、私はそれを次のように設定しています:

START = object()
END = object()

これは問題なく機能しますが、ピクルスで機能しないという問題があります。私はそれを次のようにやってみましたが、これを達成するためのひどい方法のようです:

class START(object):pass
class END(object):pass

誰かがこれを行うためのより良い手段を共有できますか?また、上記で設定した例は、別の問題を単純化しすぎたものです。

4

5 に答える 5

10

一意あることが保証され、ピクルスされたオブジェクトとピクルスされていないオブジェクト、トップレベルの関数、クラス、クラスインスタンス、およびリストisではなく気になる場合に、まったく同じIDに復元されることが保証されるオブジェクトが必要な場合(==およびその他の可変)、すべて問題ありません。つまり、次のいずれかです。

# work for == as well as is
class START(object): pass
def START(): pass
class Whatever(object): pass
START = Whatever()

# if you don't care for "accidental" == and only check with `is`
START = []
START = {}
START = set()

これらはどれもひどいものではなく、特別な利点もありません(気にするかどうかによって異なります==is。おそらくdef、一般性、簡潔さ、および軽量化の点で勝ちます。

于 2009-11-05T01:23:09.060 に答える
2

SymbolSTARTとENDを処理するためのクラスを定義できます。

class Symbol:
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        return isinstance(other, Symbol) and other.value == self.value

    def __repr__(self):
        return "<sym: %r>" % self.value

    def __str__(self):
        return str(self.value)

START = Symbol("START")
END = Symbol("END")

# test pickle
import pickle
assert START == pickle.loads(pickle.dumps(START))
assert END == pickle.loads(pickle.dumps(END))
于 2009-11-05T07:39:41.670 に答える
1

実際、私はあなたの解決策が好きです。

しばらく前、私はPythonモジュールをハッキングしていて、他のどこにも現れない特別な魔法の価値を持ちたいと思っていました。私はそれについて考えるのに少し時間を費やしました、そして私が思いついた最高のものはあなたが使ったのと同じトリックです:クラスを宣言し、そして特別な魔法の値としてクラスオブジェクトを使います。

番兵をチェックするときは、もちろんis、オブジェクトIDに演算子を使用する必要があります。

for x in my_list:
    if x is START:
        # handle start of list
    elif x is END:
        # handle end of list
    else:
        # handle item from list
于 2009-11-05T01:25:40.457 に答える
1

リストに文字列が含まれていない場合は、PythonがインターンのためにO(1)を比較するため、「start」、「end」を使用します。

タプルではなく文字列が必要な場合、完全なcheapskateメソッドは次のとおりです。

[("START",), 'foo', 'bar', 'spam', eggs', ("END",)]

PS:あなたのリストは以前は文字列ではなく数字だったと確信していましたが、リビジョンが表示されないので、想像していたに違いありません。

于 2009-11-05T01:21:14.753 に答える
0

これが何のために必要かについてもっと明確にすれば、おそらくこれは答えやすいと思いますが、このような問題に直面した場合の私の傾向は次のようになります。

>>> START = os.urandom(16).encode('hex')
>>> END = os.urandom(16).encode('hex')

私が見ているように、このアプローチの長所

  • マーカーは文字列です(特別な努力をしなくても、JSONやDBなどにピクルスにするか簡単にシリアル化できます)
  • 偶然または故意に衝突する可能性は非常に低いです
  • プロセスの再起動後も、同じ値にシリアル化および逆シリアル化されます。これは、(私が思うに)object()空のクラスには当てはまりません。

短所(?)

  • それらが新しく選ばれるたびに、それらは完全に異なります。(これが良いか悪いかは、あなたが提供していない詳細に依存すると思います)。
于 2009-11-05T01:20:10.657 に答える