[Python-Dev] Proposal: defaultdict
Nick Coghlan
ncoghlan at gmail.com
Fri Feb 17 15:27:48 CET 2006
Phillip J. Eby wrote:
> At 10:10 AM 02/17/2006 +0100, Georg Brandl wrote:
>> Guido van Rossum wrote:
>>
>>> d = DefaultDict([])
>>>
>>> can be written as simply
>>>
>>> d[key].append(value)
>>> Feedback?
>> Probably a good idea, has been proposed multiple times on clpy.
>> One good thing would be to be able to specify either a default value
>> or a factory function.
>
> +1 on factory function, e.g. "DefaultDict(list)". A default value isn't
> very useful, because for immutable defaults, setdefault() works well
> enough. If what you want is a copy of some starting object, you can always
> do something like DefaultDict({1:2,3:4}.copy).
+1 here, too (for permitting a factory function only).
This doesn't really limit usage, as you can still supply
DefaultDict(partial(copy, x)) or DefaultDict(partial(deepcopy, x)), or (heaven
forbid) a lambda expression. . .
As others have mentioned, the basic types are all easy, since the typename can
be used directly.
+1 on supplying that factory function to the constructor, too (the default
value is a fundamental part of the defaultdict). That is, I'd prefer:
d = defaultdict(func)
# The defaultdict is fully defined, but not yet populated
d.update(init_values)
over:
d = defaultdict(init_values)
# The defaultdict is partially populated, but not yet fully defined!
d.default(func)
That is, something that is the same the normal dict except for:
def __init__(self, default):
self.default = default
def __getitem__(self, key):
return self.get(key, self.default())
Considering some of Raymond's questions in light of the above
> * implications of a __getitem__ succeeding while get(value, x) returns x
> (possibly different from the overall default)
> * implications of a __getitem__ succeeding while __contains__ would fail
These behaviours seem reasonable for a default dictionary - "containment" is
based on whether or not the key actually exists in the dictionary as it
currently stands, and the default is really a "default default" that can be
overridden using 'get'.
> * whether to add this to the collections module (I would say yes)
> * whether to allow default functions as well as default values (so you could
> instantiate a new default list)
My preference is for factory functions only, to eliminate ambiguity.
# bag like behavior
dd = collections.default_dict(int)
for elem in collection:
dd[elem] += 1
# setdefault-like behavior
dd = collections.default_dict(list)
for page_number, page in enumerate(book):
for word in page.split():
dd[word].append(word)
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
http://www.boredomandlaziness.org
More information about the Python-Dev
mailing list