[Python-Dev] dict.addlist() (original) (raw)

Guido van Rossum guido at python.org
Tue Jan 20 10:34:53 EST 2004


Here is anidea to kick around:

Evolve and eventually replace dict.setdefault with a more specialized method that is clearer, cleaner, easier to use, and faster. d.addlist(k, v) would work like d.setdefault(k, []).append(v)

Raymond Hettinger >>> d = dict() >>> for elem in 'apple orange ant otter banana asp onyx boa'.split(): ... k = elem[0] ... d.addlist(k, elem) ... >>> d {'a': ['apple', 'ant', 'asp'], 'b': ['banana', 'boa'], 'o': ['orange', 'otter', 'onyx']} bookindex = dict()

(What's wrong with {}?)

for pageno, page in enumerate(pages): for word in page: bookindex.addlist(word, pageno)

I'm -0 on the idea (where does it stop? when we have reimplemented Perl?), and -1 on the name (it suggests adding a list).

It is a somewhat common idiom, but do we really need to turn all idioms into method calls? I think not -- only if the idiom is hard to read in its natural form.

bookindex = {} for pageno, page in enumerate(pages): for word in page: lst = bookindex.get(word) if lst is None: bookindex[word] = lst = [] lst.append(pageno)

works for me. (I think setdefault() was already a minor mistake -- by the time I've realized it applies I have already written working code without it. And when using setdefault() I always worry about the waste of the new empty list passed in each time that's ignored most times.)

If you really want library support for this idiom, I'd propose adding a higher-level abstraction that represents an index:

bookindex = Index() for pageno, page in enumerate(pages): for word in page: bookindex.add(word, pageno)

What you're really doing here is inverting an index; maybe that idea can be leveraged?

bookindex = Index() bookindex.fill(enumerate(pages), lambda page: iter(page))

This would require something like

class Index: def init(self): self.map = {} def fill(self, items, extract): for key, subsequence in items: for value in extract(subsequence): self.map.setdefault(value, []).append(key)

Hm, maybe it should take a key function instead:

bookindex = Index() bookindex.fill(enumerate(pages), lambda x: iter(x[1]), lambda x: x[0])

with a definition of

class Index: def init(self): self.map = {} def fill(self, seq, getitems, getkey): for item in seq: key = getkey(item) for value in getitems(item): self.map.setdefault(value, []).append(key)

Hmm... Needs more work... I don't like using extractor functions. But I like addlist() even less.

--Guido van Rossum (home page: http://www.python.org/~guido/)



More information about the Python-Dev mailing list