Python with语句:存储contex

2024-04-24 04:36:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试改进(如果可能的话)下面的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

用法示例:

^{pr2}$

输出:

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

对于大型数据结构,copy可能很昂贵。在上下文中只存储对数据结构的更改,然后在^{期间撤消对数据的那些特定更改,这是(或有没有)一种干净的方法?


Tags: storeself数据结构objectinitdeftypecontext
2条回答

您可以使用数据库作为底层存储来实现Store,并且只需ROLLBACK。在

你可以使用某种检查点。例如,可以保留一个单独的结构,在其中插入新元素。退出上下文时,需要从容器中删除这些新元素。在

显然,这是否值得与深度合作相比取决于以下几个因素:

  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

当然,这是一个非常简单的例子,为了添加对从列表中任何位置移除元素的支持,您需要保留对列表执行的操作的某种日志。日志可以是指定操作类型(插入、删除)及其参数(例如索引、数据)的条目列表。此外,如果您想支持所有列表操作,则需要使用代理或包装器来拦截列表上的每个修改操作(例如,appendextendinsertremove,等等)。在

如果您想更通用,不仅支持列表,还支持其他类型的容器,那么您需要包装器来操作不同的容器。例如,对于set,您需要支持addremoveupdateintersection_update等。要做到这一点,您可以创建一个从DataContext递减的类层次结构,并对每种类型执行专门的操作。在

总之,正如您所看到的,实现这一点的复杂性会显著增加,这取决于您希望成为多大程度的泛型。因此,如果您只想为列表定制一个特定的解决方案,那么实现它可能会有回报,否则,最好支付执行容器副本的代价。在

相关问题 更多 >