我正在尝试:
award_dict = {
"url" : "http://facebook.com",
"imageurl" : "http://farm4.static.flickr.com/3431/3939267074_feb9eb19b1_o.png",
"count" : 1,
}
def award(name, count, points, desc_string, my_size, parent) :
if my_size > count :
a = {
"name" : name,
"description" : desc_string % count,
"points" : points,
"parent_award" : parent,
}
a.update(award_dict)
return self.add_award(a, siteAlias, alias).award
但是如果觉得这个功能真的很麻烦,我宁愿做完:
return self.add_award({
"name" : name,
"description" : desc_string % count,
"points" : points,
"parent_award" : parent,
}.update(award_dict), siteAlias, alias).award
为什么不更新返回对象以便链接?
JQuery这样做是为了链接。为什么在python中它不可接受?
答案 0 :(得分:185)
Python主要实现command-query separation的实用主义风格:mutators返回None
(使用实际引发的异常,例如pop
;-),因此它们不可能与访问者混淆(同样,赋值不是表达式,语句表达式分离就在那里,等等。
这并不意味着在您真正想要的时候没有很多方法可以合并,例如,dict(a, **award_dict)
制作一个新的dict,就像您希望.update
返回的那个 - 那么,如果你真的觉得这很重要,为什么不使用它?
修改:顺便说一下,在您的具体情况下,无需在此过程中创建a
:
dict(name=name, description=desc % count, points=points, parent_award=parent,
**award_dict)
创建一个与a.update(award_dict)
具有完全相同语义的单个dict(如果发生冲突,则包括award_dict
中的条目覆盖您明确给出的条目;获取其他语义,即,有明确的条目“赢得”此类冲突,将award_dict
作为唯一的位置 arg,在关键字之前传递,并且丧失{{ 1}} form - **
等等。)
答案 1 :(得分:32)
这样做的动机是否则会产生不良副作用。考虑
bar = foo.reverse()
如果反向(就地反转列表)也会返回列表,用户可能会认为反向返回一个新的列表,该列表被分配给bar,并且从不会注意到foo也会被修改。通过反向返回None,他们立即意识到条形不是反转的结果,并且看起来更接近反向的影响。
答案 2 :(得分:13)
>>> dict_merge = lambda a,b: a.update(b) or a
>>> dict_merge({'a':1, 'b':3},{'c':5})
{'a': 1, 'c': 5, 'b': 3}
请注意,除了返回合并的dict之外,它还会就地修改第一个参数。所以dict_merge(a,b)将修改。
或者,当然,你可以全部内联:
>>> (lambda a,b: a.update(b) or a)({'a':1, 'b':3},{'c':5})
{'a': 1, 'c': 5, 'b': 3}
答案 3 :(得分:7)
没有足够的评论声誉留在最佳答案
@beardc这似乎不是CPython的事情。 PyPy给了我" TypeError:关键字必须是字符串"
只有**kwargs
的解决方案才有效,因为要合并的字典只有类型为字符串的键。
即
>>> dict({1:2}, **{3:4})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings
VS
>>> dict({1:2}, **{'3':4})
{1: 2, '3': 4}
答案 4 :(得分:5)
这不是不可接受的,而是dicts
没有以这种方式实现。
如果你看一下Django的ORM,它会广泛使用链接。如果你真的想要它,你甚至可以从dict
继承,只覆盖update
进行更新和return self
。
class myDict(dict):
def update(self, *args):
dict.update(self, *args)
return self
答案 5 :(得分:4)
这很容易,因为:
public function getFormats()
{
$image = Storage::disk('dospace')->url($this->image);
//dd($image);
$imageContent = file_get_contents(Storage::disk('dospace')->url($this->image));
$width = Image::make($imageContent)->width();
$height = Image::make($imageContent)->height();
$sizes = [
'width' => $width,
'height' => $height
];
return $sizes;
}
答案 6 :(得分:2)
尽可能接近你提出的解决方案
from collections import ChainMap
return self.add_award(ChainMap(award_dict, {
"name" : name,
"description" : desc_string % count,
"points" : points,
"parent_award" : parent,
}), siteAlias, alias).award
答案 7 :(得分:0)
import itertools
dict_merge = lambda *args: dict(itertools.chain(*[d.iteritems() for d in args]))
答案 8 :(得分:0)
我自己在Python 3.4中尝试过这种方法(因此无法使用花哨的{**dict_1, **dict_2}
语法)。
我希望能够在字典中使用非字符串键,并提供任意数量的字典。
另外,我想制作一个新词典,所以我选择不使用collections.ChainMap
(有点我最初不想使用dict.update
的原因。
这是我最后写的内容:
def merge_dicts(*dicts):
all_keys = set(k for d in dicts for k in d.keys())
chain_map = ChainMap(*reversed(dicts))
return {k: chain_map[k] for k in all_keys}
merge_maps({'1': 1}, {'2': 2, '3': 3}, {'1': 4, '3': 5})
# {'1': 4, '3': 5, '2': 2}
答案 9 :(得分:0)
对于那些迟到的人,我已经安排了一些时间安排(Py 3.7),这表明基于.update()
的方法在保留输入的情况下看起来快了(〜5%),并且明显地(〜30%) ),只需就地更新即可。
与往常一样,所有基准测试都应加一粒盐。
def join2(dict1, dict2, inplace=False):
result = dict1 if inplace else dict1.copy()
result.update(dict2)
return result
def join(*items):
iter_items = iter(items)
result = next(iter_items).copy()
for item in iter_items:
result.update(item)
return result
def update_or(dict1, dict2):
return dict1.update(dict2) or dict1
d1 = {i: str(i) for i in range(1000000)}
d2 = {str(i): i for i in range(1000000)}
%timeit join2(d1, d2)
# 258 ms ± 1.47 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit join(d1, d2)
# 262 ms ± 2.97 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit dict(d1, **d2)
# 267 ms ± 2.74 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit {**d1, **d2}
# 267 ms ± 1.84 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
就地操作的时序有些棘手,因此需要通过额外的复制操作进行修改(第一个时序仅供参考):
%timeit dd = d1.copy()
# 44.9 ms ± 495 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit dd = d1.copy(); join2(dd, d2)
# 296 ms ± 2.05 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit dd = d1.copy(); join2(dd, d2, True)
# 234 ms ± 1.02 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit dd = d1.copy(); update_or(dd, d2)
# 235 ms ± 1.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)