dicttoolz has functions for working with these objects; including dicttoolz.merge (which returns a reference to the merged dicts but does not mutate the arguments passed).
https://toolz.readthedocs.io/en/latest/api.html#dicttoolz https://toolz.readthedocs.io/en/latest/api.html#toolz.dicttoolz.merge pyrsistent has a PRecord class with invariants and type checking that precedes dataclasses. pyrsistent also has 'freeze' and 'thaw' functions for immutability. PRecord extends PMap, which implements __add__ as self.update(arg) (which does not mutate self) https://github.com/tobgu/pyrsistent/blob/master/README.rst#precord https://github.com/tobgu/pyrsistent/blob/master/pyrsistent/_pmap.py On Tuesday, March 5, 2019, Guido van Rossum <gu...@python.org> wrote: > If you have to tell such a long and convoluted story to explain a name > that you've picked out of the blue and that has no equivalent in other > Python data types, it's probably a bad idea. If you're proposing that other > mutating methods also gain a flow_XXX variant, please, no! That's like the > theory of supersymmetry (SUSY) in particle physics, where ever known > particle from the Standard Model would have to have a much heavier > "superpartner" just to make some esoteric idea work. > > On Tue, Mar 5, 2019 at 12:54 AM Jonathan Fine <jfine2...@gmail.com> wrote: > >> SUMMARY >> Instead of using dict + dict, perhaps use dict.flow_update. Here, >> flow_update is just like update, except that it returns self. >> >> BACKGROUND >> There's a difference between a sorted copy of a list, and sorting the >> list in place. >> >> >>> items = [2, 0, 1, 9] >> >>> sorted(items), items >> ([0, 1, 2, 9], [2, 0, 1, 9]) >> >>> items.sort(), items >> (None, [0, 1, 2, 9]) >> >> In Python, mutating methods generally return None. Here, this prevents >> beginners thinking their code has produced a sorted copy of a list, >> when in fact it has done an in-place sort on the list. If they write >> >>> aaa = my_list.sort() >> they'll get a None error when they use aaa. >> >> The same goes for dict.update. This is a useful feature, particularly >> for beginners. It helps them think clearly, and express themselves >> clearly. >> >> THE PROBLEM >> This returning None can be a nuisance, sometimes. Suppose we have a >> dictionary of default values, and a dictionary of use supplied >> options. We wish to combine the two dictionaries, say into a new >> combined dictionary. >> >> One way to do this is: >> >> combined = defaults.copy() >> combined.update(options) >> >> But this is awkward when you're in the middle of calling a function: >> >> call_big_method( >> # lots of arguments, one to a line, with comments >> arg = combined, # Look up to see what combined is. >> # more arguments >> ) >> >> USING + >> There's a suggestion, that instead one extends Python so that this works: >> arg = defaults + options # What does '+' mean here? >> >> USING flow_update >> Here's another suggestion. Instead write: >> dict_arg = defaults.copy().flow_update(options) # Is this >> clearer? >> >> IMPLEMENTATION >> Here's an implementation, as a subclass of dict. >> >> class mydict(dict): >> >> def flow_update(self, *argv, **kwargs): >> self.update(*argv, **kwargs) >> return self >> >> def copy(self): >> return self.__class__(self) >> >> A DIRTY HACK >> Not tested, using an assignment expression. >> dict_arg = (tmp := defaults.copy(), tmp.update(options))[0] >> Not recommend. >> >> -- >> Jonathan >> _______________________________________________ >> Python-ideas mailing list >> Python-ideas@python.org >> https://mail.python.org/mailman/listinfo/python-ideas >> Code of Conduct: http://python.org/psf/codeofconduct/ >> > > > -- > --Guido van Rossum (python.org/~guido) >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/