为什么python dict.update()没有返回对象?

我正在尝试做:

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 

但是如果在function上感觉真的很麻烦,而且我宁愿做:

  return self.add_award({ "name" : name, "description" : desc_string % count, "points" : points, "parent_award" : parent, }.update(award_dict), siteAlias, alias).award 

为什么不更新返回的对象,所以你可以链?

JQuery这样做链接。 python为什么不可以接受?

Python的主要实现命令 – 查询分离的实用色彩风格:mutators返回None (与实用引发的exception,如pop ;-),所以他们不可能与访问者混淆(并在同一脉络,赋值不是一个expression式,语句expression式分离在那里,等等)。

这并不意味着当你真正想要的时候没有什么合并的方法,例如, dict(a, **award_dict)使得一个新的字典与你所希望的.update返回 – 所以为什么不使用,如果你真的觉得这很重要?

编辑 :顺便说一句,在你的具体情况,无需创builda方法,无论是:

 dict(name=name, description=desc % count, points=points, parent_award=parent, **award_dict) 

创build一个与您的a.update(award_dict)完全相同的语义(包括在冲突的情况下, award_dict中的条目覆盖您明确给出的条目;获取其他语义,即明确的条目“赢得”这样的冲突,通过award_dict作为唯一的位置 arg, 关键字之前 ,并且没有** form- dict(award_dict, name=name等等)。

Python的API按照惯例区分程序和函数。 函数从参数中计算新值(包括任何目标对象); 过程修改对象,不返回任何东西(即他们返回None)。 所以程序有副作用,function不行。 更新是一个过程,因此它不会返回一个值。

这样做的动机是,否则,你可能会得到不希望的副作用。 考虑

 bar = foo.reverse() 

如果反向(反向列表就地)也将返回列表,用户可能会认为反向返回一个新的列表,它将被分配给bar,并且永远不会注意到foo也会被修改。 通过做出逆向回报没有,他们立即认识到,酒吧不是逆转的结果,并且会看起来更接近逆转的效果。

 >>> 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_merge(a,b)会修改一个。

或者,当然,你可以全部内联:

 >>> (lambda a,b: a.update(b) or a)({'a':1, 'b':3},{'c':5}) {'a': 1, 'c': 5, 'b': 3} 

这并不是说这是不可接受的,而是说这些dicts不是这样执行的。

如果你看Django的ORM,它会大量使用链接。 它不泄气,你甚至可以inheritancedict ,只有重写update做更新和return self ,如果你真的想要它。

 class myDict(dict): def update(self, *args): dict.update(self, *args) return self 

没有足够的评论留下最好的答案

@beardc这似乎不是CPython的事情。 PyPy给我“TypeError:关键字必须是string”

带有**kwargs的解决scheme只能工作,因为要合并的字典只有stringtypes的键

 >>> 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} 
 import itertools dict_merge = lambda *args: dict(itertools.chain(*[d.iteritems() for d in args])) 

尽可能接近您提出的解决scheme

 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 

刚刚在Python 3.4中自己尝试这个(所以不能使用花哨的{**dict_1, **dict_2}语法)。

我希望能够在字典中使用非string键以及提供任意数量的字典。

另外,我想创build一个新的字典,所以我select不使用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}