为什么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}