Skip to main content
 首页 » 编程设计

带有语句 : storing context 的 Python

2025年05月04日10pengyingh

我正在尝试改进(如果可能的话)下面的 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 期间撤消对数据的这些特定更改?

请您参考如下方法:

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

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

  1. 底层容器。并非所有容器都具有相同的 API,因此您需要针对不同的受支持容器类型专门化检查点机制(这可能并非易事)。
  2. 进入上下文之前的元素数量与在上下文中插入的元素数量之比是多少。

此外,就正确性而言,容器的类型也会影响这种机制的设计。例如,如果容器是一个列表,您需要删除在上下文中插入的所有元素。另一方面,如果容器是一个集合,则只需在它们最初不存在时将其删除。

为了简单起见,假设你只对列表感兴趣并且只支持append操作,那么一个可能的解决方案其实很简单:

类数据上下文(对象):

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、extend、insert、remove 等)如果你想支持所有的列表操作。

如果您想变得更加通用并且不仅支持列表而且还支持其他类型的容器,那么您将需要对不同容器的操作进行包装。例如,对于 set,您需要支持 add、remove、update、intersection_update 等。要做到这一点,您可以创建一个从 DataContext 下降的类层次结构,并对每种类型进行专门的操作。

无论如何,如您所见,实现这一点的复杂性会显着增加,具体取决于您希望通用性的程度。因此,如果您只是想要一个为列表量身定制的特定解决方案,那么实现它可能会有所返回,否则最好付出执行容器副本的代价。