跟踪数据结构的变化。

difftrack的Python项目详细描述


difftrack是跟踪数据结构更改的工具。 它使多个“侦听器”可以看到 要更改的dict、list或任何其他数据结构 观察和支持(这些结构称为“调度员”)。

difftrack有两个主要类:

  • Dispatcher-就像一个数据结构,你可以向它写入数据,也可以发送数据 对其所有侦听器的所有更改(diff)。
  • Listener-一个侦听器连接到一个调度程序并应用输入 与内部结构不同,因此每个侦听器看起来都像原始数据 应用所有这些差异后的结构。

此分区允许difftrack在 应用diff的不同阶段,它使侦听器 有特殊的缩写(例如difftrack.utils.BoundedListDiffHandler 实现“前n个”列表:列表永远不会超过某个固定大小 但当删除某些项目时,会出现以前不可见的元素)。

基本用法

在下面的示例中,我们将创建一个列表分派器(您可以 使用__setitem__,^{tt8}将其作为列表写入$ 以及insert)和两个侦听器,它们将侦听diff并保持 他们自己的内部状态。

>>>importdifftrack>>>dispatcher=difftrack.ListDispatcher()>>>listener1=difftrack.ListListener()>>>listener2=difftrack.ListListener()>>>dispatcher.add_listener(listener1)>>>dispatcher.add_listener(listener2)# create listeners and add them to dispatcher>>>dispatcher.insert(0,'AAA')# insert string 'AAA' to the first position in list>>>listener1.get_snapshot()# Diffs are not applied until get_new_diffs() is called[]>>>listener1.get_new_diffs()# now we get all diffs that have not been processed yet[(difftrack.ListDiff.INSERT,0,'AAA')]>>>listener1.get_snapshot()# and we see that listener1's snapshot now contains what we expect['AAA']>>>listener2.get_snapshot()# second listener still hasn't got anything because we haven't read its diffs[]>>>dispatcher.insert(0,'BBB')# insert new string to 'BBB'>>>listener1.get_new_diffs()# we need to read new diffs to get current state[(difftrack.ListDiff.INSERT,0,'BBB')]>>>listener1.get_snapshot()# we inserted 'BBB' to first position so 'AAA' was moved to second position['BBB','AAA']>>>deldispatcher[0]# remove the first element from th list (now 'BBB')>>>listener1.get_new_diffs()[(difftrack.ListDiff.DELETE,0,None)]>>>listener1.get_snapshot()# we deleted 'BBB' so only 'AAA' remains['AAA']>>>dispatcher[0]='CCC'# overwrite the first element>>>listener1.get_new_diffs()[(difftrack.ListDiff.REPLACE,0,'CCC')]>>>listener1.get_snapshot()['CCC']# the first and only element in list was overwritten>>>listener2.get_new_diffs()# finally get all diffs for listener2[(<ListDiff.INSERT:0>,0,'AAA'),(<ListDiff.INSERT:0>,0,'BBB'),(<ListDiff.DELETE:2>,0,None),(<ListDiff.REPLACE:1>,0,'CCC')]>>>listener2.get_snapshot()# listener2 is now also up to date['CCC']

类似地,可以将difftrackDictDispatcherDictListener:将更改写入 DictDispatcher在对侦听器应用diff之后,可以得到 当前字典状态的快照。

回调

on_change

我们还可以向侦听器添加回调,以便在 来了:

importdifftrack>>>dispatcher=difftrack.ListDispatcher()>>>defdouble_inserted_items(dtype,index,value):''' This generates a new diff *while the current one is processed!* '''ifdtypeisdifftrack.ListDiff.INSERT:dispatcher[index]=value*2>>>listener=difftrack.ListListener(on_change=double_inserted_items)# set function as a callback>>>dispatcher.add_listener(listener)>>>dispatcher.insert(0,7)# insert 7 at index 0 and expect that the result will be doubled>>>listener.get_new_diffs()[(difftrack.ListDiff.INSERT,0,7),(difftrack.ListDiff.REPLACE,0,14)]>>>listener.get_snapshot()[14]

在这个例子中,我们展示了on_change回调及其 和调度员一起工作。注意,我们首先使用 ListDiff.INSERT操作,但回调会触发 ListDiff.REPLACE操作。如果它再次导致ListDiff.INSERT,我们 以递归结束,10次迭代后difftrack将放弃并 提出一个例外。

on_finalize_batch

调度器可以向它的侦听器通信某个序列 差分属于一起,即形成一个batch。我们通过使用 Dispatcher作为上下文管理器,包装属于一起的diff操作。

侦听器可以提供另一个名为on_finalize_batch 每次调度程序完成批处理调度时调用。 (上下文已退出)。

>>>importdifftrack>>>dispatcher=difftrack.DictDispatcher()>>>deffinalize():print('FINALIZED')>>>defon_change(*args):print('CHANGE')>>>listener=difftrack.DictListener(on_change=on_change,on_finalize_batch=finalize)>>>dispatcher.add_listener(listener)>>>withdispatcher:# use the dispatcher as a context managerdispatcher[0]=0dispatcher[1]=1dispatcher[2]=2CHANGECHANGECHANGEFINALIZED

我们可以看到每次都调用on_change回调,但是 {TT20}$仅当我们退出上下文时。

实用程序

您可能会发现有几个实用程序很有用。

data_mapper

数据映射器对每个数据字段应用一个函数:

>>>importdifftrack>>>defmapper(data:str)->str:returndata.lower()>>>dispatcher=difftrack.ListDispatcher()>>>listener=difftrack.ListListener()>>>dispatcher.add_listener(difftrack.data_mapper(mapper)(listener))>>>dispatcher.insert(0,'AAA')>>>dispatcher.insert(0,'BBB')>>>listener.get_new_diffs()[(difftrack.ListDiff.INSERT,0,'aaa'),(difftrack.ListDiff.INSERT,0,'bbb')]>>>listener.get_snapshot()['bbb','aaa']

compact_dict_diffs

当你多次更新一个dict项,甚至删除它时 有时不想保留所有的变化。您可以使用压缩 删除相互取消或覆盖的更改:

>>>diffs=[(difftrack.DictDiff.SET,'x',123),(difftrack.DictDiff.SET,'y',456),(difftrack.DictDiff.SET,'y',9999),(difftrack.DictDiff.DELETE,'x',None),]>>>difftrack.compact_dict_diffs(diffs)[(difftrack.DictDiff.SET,'y',9999),(difftrack.DictDiff.DELETE,'x',None),]

compact_list_diffs

同样的压缩也适用于列表:

>>>diffs=[(difftrack.ListDiff.INSERT,0,'aaa'),(difftrack.ListDiff.INSERT,1,'bbb'),(difftrack.ListDiff.DELETE,0,None)(difftrack.ListDiff.REPLACE,1,'ccc'),]>>>difftrack.compact_list_diffs(diffs)[(difftrack.ListDiff.INSERT,1,'ccc'),]

BoundedListDiffHandler

如果我们想保持列表有界(限制到一定的大小),我们可以使用 difftrack.BoundedListDiffHandler

>>>importdifftrack>>>listener=difftrack.ListListener()>>>dispatcher=difftrack.ListDispatcher()>>>dispatcher.add_listener(difftrack.BoundedListDiffHandler(listener,2))# bound listener to 2 elements>>>dispatcher.insert(0,'a')>>>dispatcher.insert(1,'b')>>>dispatcher.insert(2,'c')>>>dispatcher.insert(3,'d')>>>listener.get_new_diffs()[(difftrack.ListDiff.INSERT,0,'a'),(difftrack.ListDiff.INSERT,1,'b'),]>>>listener.get_snapshot()['a','b']>>>deldispatcher[0]>>>listener.get_new_diffs()# 'a' is deleted and 'c' moves to the empty index 1[(<ListDiff.DELETE:2>,0,None),(<ListDiff.INSERT:0>,1,'c')]>>>listener.get_snapshot()['b','c']

squash_list_diffs

此函数组列出影响连续索引的差异。

>>>importdifftrack>>>diffs=[(difftrack.ListDiff.INSERT,1,'A'),(difftrack.ListDiff.INSERT,2,'B'),(difftrack.ListDiff.INSERT,3,'C'),(difftrack.ListDiff.REPLACE,1,'D'),(difftrack.ListDiff.DELETE,1,[])]>>>list(difftrack.squash_list_diffs(diffs))[SquashResults(operation=<difftrack.ListDiff.INSERT:0>,start=1,stop=1,payload=['A','B','C']),SquashResults(operation=<difftrack.ListDiff.REPLACE:1>,start=1,stop=2,payload=['D']),SquashResults(operation=<difftrack.ListDiff.DELETE:2>,start=1,stop=2,payload=[])]

您可以看到三个连续的插入被压缩成一条消息。注意结果 不再是difftrack diff。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java禁用主窗口但显示模块   java Eclipse jre 1.5>1.8   java测试Eclipse4RCP应用程序。提供必要的物品   当我键入命令时,java spiget会识别它,但当我按enter键时,什么也不会发生   引用数组中的对象的C++ java   Java Axis Web服务重载控制   java如何实现重载方法以正确识别变量   java将数组元素与下一个数组进行比较,并在该元素为新元素时重新开始   java gradle依赖项的“编译组”是什么?不同的组件做什么?   java为什么哈希代码比类似的方法慢?   Struts 2中的java HttpServletRequest和静态方法threadsafety   我想用JavaSwing中的JButtons制作一个六边形表格   jaxb通过多个标记名选项将XML映射到Java   如何在centOS上安装Apache Tomcat   java优化N Queens代码以避免堆栈溢出   java如何找到AST表达式的底部