2

以下の DataContext クラスを (可能であれば) 改善するか、別の解決策を見つけようとしています。

class Store(object):

    def __init__( self, contents=None):
        self.contents = contents

class DataContext(object):

    def __init__( self, datastore ) : # datastore is of type store
        self.store = datastore

    def __enter__( self ) :
        self.temp_store = copy.copy( self.store.contents )  # Improve upon this!

    def __exit__( self, type, value, traceback ) :
        self.store.contents = self.temp_store

使用例:

data = Store( [1,2,3] )
print "Before context: ", data.contents
with DataContext( data ):
    data.contents.append( 4 )         # Tampering with the data 
    print "Within context: ", data.contents

print "Outside context: ", data.contents

出力:

Before context:  [1, 2, 3]
Within context:  [1, 2, 3, 4]
Outside context:  [1, 2, 3]

copy規模なデータ構造の場合、コストが高くなる可能性があります。コンテキスト内のデータ構造への変更のみを保存し、実行中にデータへの特定の変更を元に戻すためのクリーンな方法は何ですか (またはありexitますか? )

4

2 に答える 2

1

ある種のチェックポイントを使用できます。たとえば、新しい要素を挿入する別の構造を保持できます。コンテキストを終了したら、これらの新しい要素をコンテナーから削除する必要があります。

明らかに、これが深い協力を行うことと比較して価値があるかどうかは、次のようないくつかの要因に依存します。

  1. 基になるコンテナー。それらのすべてが同じ API を持っているわけではないため、サポートされているさまざまなコンテナー タイプに合わせてチェックポイント メカニズムを特殊化する必要があります (それは簡単ではないかもしれません)。
  2. コンテキストに入る前の要素と、コンテキスト内に挿入された要素の数の比率は?

さらに、正確さの観点から、コンテナのタイプもそのようなメカニズムの設計に影響します。たとえば、コンテナーがリストの場合、コンテキスト内で挿入したすべての要素を削除する必要があります。一方、コンテナがセットの場合、それらが最初に存在しなかった場合にのみ削除する必要があります。

簡単にするために、リストと操作のサポートのみに関心があると仮定しましょう。その場合append、考えられる解決策は実際には非常に簡単です。

クラス DataContext(オブジェクト):

def __init__( self, datastore ) : # datastore is of type store
    self.store = datastore
    self.num_added = 0

def __enter__( self ) :
    pass

def __exit__( self, type, value, traceback ) :
    l = len(self.store.contents)
    del self.store.contents[l - self.num_added : l]

def append( self, elem ) :
    self.store.contents.append(elem)
    self.num_added += 1

確かにこれは非常に単純なケースであり、リスト内の任意の場所から要素を削除するためのサポートを追加するためだけに、リストで実行された操作の何らかのログを保持する必要があります。ログは、操作のタイプ (挿入、削除) とその引数 (インデックス、データなど) を指定するエントリのリストである可能性があります。さらに、すべてのリスト操作をサポートしたい場合は、プロキシまたはラッパーを使用して、リストのすべての変更操作 (例: 、 、 、 など) をインターセプトする必要がありappendます。extendinsertremove

さらに汎用化し、リストだけでなく他の種類のコンテナーをサポートする場合は、さまざまなコンテナーの操作用のラッパーが必要になります。たとえば、、、 、 などをsetサポートする必要があります。そのためには、各タイプに特化した操作でから派生するクラス階層を作成できます。addremoveupdateintersection_updateDataContext

とにかく、ご覧のとおり、これを実装するための複雑さは、どれだけジェネリックになりたいかによって大幅に増加します。したがって、おそらく、リスト用に調整された特定のソリューションが必要な場合は、それを実装することで利益が得られる可能性があります。そうでない場合は、コンテナーのコピーを実行するという代償を支払う方がよい場合があります。

于 2012-05-24T22:32:35.427 に答える
0

Store基礎となるストレージとしてデータベースを使用して実装できますROLLBACK

于 2012-05-25T06:52:56.943 に答える