我在一些代码中看到了这种模式,我正在写
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..
我在一些队列上解复用一个事件,但每个队列的格式略有不同。我已经开始这样做了:
queue.push( dict(e.items() + [("table":"users"), ("timestamp", time.time())]) )
但它看起来很难看,它会减慢代码速度。我还能做什么?
答案 0 :(得分: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__
,具体取决于{{1} }需要)。
用法:
push
或:
other = {"table": "users", "timestamp": time.time()}
queue.push(MergedDicts(e, other))
答案 1 :(得分:1)
如果对字典的修改次数与字典本身的大小相比相对较小,则可以通过创建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
答案 2 :(得分:0)
您可以使用所需的新字段创建新字典,并在其上使用dict.update
和基本字段
e = {...} # a dictionary
d={"table":"users", "timestamp":time.time()}
d.update(e)
queue.push(d)
您还可以使用字段作为列表创建新的dict:
e = {...} # a dictionary
queue.push( e.items() + [("table","users"), ("timestamp",time.time())] )
如果你在大型词典上做了很多,并且不想创建副本,你可以使用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 )
答案 3 :(得分:0)
如果您最初只使用每个用例共有的键定义e
,则可以使用mock
库。 mock.patch.dict
允许您临时将字符串添加到字典中(在with
语句的持续时间内),但您无法暂时删除键。
e = { ... }
with mock.patch.dict(e, table="users", timestamp=time.time()):
queue.push(e)
with mock.patch.dict(e, table="events"):
queue2.push(e)
mock
是Python 2.x的第三方模块,在Python 3.4之前,它已作为unittest.mock
添加到标准库中。
答案 4 :(得分:0)
我认为它可能会被下一个代码覆盖:
a = {'val': 2, 'val2': -5, "name": 'Vladimir'}
b = {"asdf": 1, "b2": 2}
queue.push( dict( **a, **b) )