python动态临时修改dict的方法

2024-10-04 05:20:12 发布

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

我在我写的一些代码中看到了这种模式

e = {...} # a dictionary
e["table"] = "users"
e["timestamp"] = time.time()
queue.push(e)
del e["table"]
del e["timestamp"]
[...]
e["table"] = "events"
queue2.push(e)
del e["table"]
# etc..

我将事件分解到一些队列上,但每个队列的格式略有不同。我已经开始这样做了:

^{pr2}$

但它看起来很难看,而且会减慢代码的速度。我还能做什么?在


Tags: 代码dictionarytime队列queuetable模式etc
3条回答

假设queue.push只需要读访问权限,可以尝试如下操作:

class MergedDicts(dict):
    def __init__(self, *dicts, **kw):
        self.dicts = dicts + (kw,)

    def __getitem__(self, key):
        for d in self.dicts:
            if key in d: return d[key]
        raise KeyError(key)

这将为您提供一个从两个源返回项的字典,但避免了从原始源构建另一个实际副本的开销(但是,您可能需要实现的不仅仅是__getitem__,这取决于push需要什么)。在

用法:

^{pr2}$

或者:

queue.push(MergedDicts(e, table="users", timestamp=time.time()))

如果与字典本身的大小相比,对字典的修改数量相对较小,则可以通过创建context manager函数并按如下所示使用它来避免每次都复制它。这将确保对字典所做的任何更改都是临时的,即使在块内使用时引发了异常。在

from contextlib import contextmanager

@contextmanager
def contextdict(adict, **kwargs):
    # modify dictionary
    changed = {}
    added = []
    for key in kwargs:
        if key in adict:
            changed[key] = adict[key]
        else:
            added.append(key)
        adict[key] = kwargs[key]
    yield adict
    # restore dictionary
    adict.update(changed)
    for key in added:
        del adict[key]

e = dict(...)  # some dictionary

with contextdict(e, table="users", timestamp=time.time()) as context:
    queue.push(context)
with contextdict(e, table="events") as context:
    queue.push(context)

# e will be unchanged at this point

您可以使用所需的新字段创建一个新字典,并在其上使用dict.update与基字段一起使用

e = {...} # a dictionary
d={"table":"users", "timestamp":time.time()}
d.update(e)
queue.push(d)

您还可以创建一个新的dict,其中的字段为列表:

^{pr2}$

如果您经常在大型词典上执行此操作,并且不想创建副本,则可以使用一个Context Manager临时修改词典,使您现在正在执行的操作自动化。在


另一个选项(而不是上下文管理器)是在函数中执行修改,将要执行的操作作为函数传递:

def modify_dict_and_call( d, newfields, f):
    for k,v in newfields.items():
        d[k]=v
    f(d)
    for k in newfields:
        del d[k]

e = {...} # a dictionary
modify_dict_and_call( e, {"table":"users", "timestamp":time.time()}, queue.push )

相关问题 更多 >