enhancing dictionary update method and the dict type constructor

Tim Peters tim.one at home.com
Sat Nov 17 15:09:38 EST 2001


[Alexis Layton]
> This message proposes two minor enhancements. Since I've missed the
> feature freeze for Python 2.2, this would be for the next version.
>
> The first enhacement improves the definition of the dictionary "update"
> method, the second enhancement broadens the dictionary type constructor.
>
> In Python 2.2, the new dictionary type factory function "dict"
> (previously known as "dictionary" in 2.2b1) takes either a mapping
> object or a sequence of key, value pairs as its argument.
>
> I would like to propose that the dictionary method "update" be broadened
> to take a similar argument type.

Sorry, Guido already rejected this idea (proposed by me) in a PythonLabs mtg
a few weeks ago.  Your hypothetical

    adict.update(pairs)

can be spelled

    adict.update(dict(pairs))

in 2.2.  I agree with the rejection:  it's marginally cool for the factory
constructor to convert from different representations, but there was no
intent that sequence-of-pairs be a generally accepted alternative
representation for dicts (kinda similarly, 24 + int("42") works but not 24 +
"42" -- Python is conservative about magical conversions).

> In addition, I believe it would be generally useful if the sequence
> form allowed singleton sequences to represent keys that should be
> omitted from the dictionary, thus:
>
> 	d = {'a': 1, 'b': 2}
> 	d.update([('a',), ('b', 0), ('c', 3)])
> 	print d
> 	{'c': 3, 'b': 0}

Since d.update(pairs) is dead on arrival, enhancements to it probably don't
stand a better chance <wink>.  I especially squirm at this one, since, e.g.,
it would mean that

    d.update("oops")

deletes the keys "o", "p" and "s" from d ("oops" is a sequence of
1-sequences), and that's way too obscure.

> I propose that non-existant keys specified in such an update sequence be
> silently ignored.
>
> Given such an expansion of update, it seems to me the more useful
> constructor for dictionaries would be something more akin to:
>
> 	def dict(*mss):
> 		d = { }
> 		for map_or_sequence in mss:
> 			d.update(map_or_sequence)
> 		return d
>
> This permits several useful idioms, such as the common case in
> environment binding where a dictionary represents a symbol table and one
> must construct a subsidiary dictionary in which one binding has changed:
>
> 	d2 = dict(d, ('v', 3))

    d2 = d.copy()
    d['v']  = 3

> It also permits the "union" of two or more dictionaries: dict(d1, d2).

    d = d1.copy()
    d.update(d2)

> ASIDE: what is the proper term for this, since keys in d2 can override
> those in d1?

"update", as in d.update().  The Python C API is a little richer:
PyDict_Update actually calls PyDict_Merge with an "override" flag;
PyDict_Merge can be told to let the keys of either input dict "win".

> Finally, for years I've had a little utility function (called "dict" by
> the way) which constructs dictionaries in which all the keys are
> identifiers anyway using the keyword syntax:
>
> 	def dict(**kw): return kw
>
> The reason is mostly to pre-load certain stupid little look-up tables
> using a more convenient syntax: dict(a=1, b=2, c=3), etc.

Yes, it's a pleasant technique.  The good news is that, except for the name,
it's not being taken away.

> The type constructor could also have a **kw behavior which is the final
> update into the new dictionary, as if dict was defined to be:
>
> 	def dict(*mss, **kw):
> 		d = { }
> 		for ms in mss:
> 			d.update(ms)
> 		d.update(kw)
> 		return d

At this point I would despair of explaining what the dict() function does,
and it's not our goal to build in all possible 3-line functions <wink>.
There have been about a dozen other ideas for extending the dict() function
too; adding sequence-of-pairs was our best stab at implementing the most
useful one; most others appear to have an audience of one.





More information about the Python-list mailing list