Вопрос

I have a function:

#Should be named tryAppendingToListInADict but I'm too lazy for that long of a name
def tryAppendingToDict(dictionary, key, item):
    try:
        #append to an existing list
        dictionary[key].append(item)
    except KeyError:
        #list doesn't exist yet, so make one
        dictionary[key] = [item]

In most cases I use this function on one dictionary, let's call it defaultDictOfLists, as in my code looks like

tryAppendingToDict(defaultDictOfLists, 'spam', 'eggs')
tryAppendingToDict(defaultDictOfLists, 'spam', 'beacon')
tryAppendingToDict(defaultDictOfLists, 'not spam', 'yuck!')
#...
tryAppendingToDict(differentDict, 'spam', 'I don't like spam!')

So I wanted to try and make a keyword argument to my function that would assume you're appending items to the defaultDictOfLists. However, the main problem here, is that this function is imported from a separate module (and should remain there), so a simple

def tryAppendingToDict(key, item, dictionary = defaultDictOfLists):

raises a NameError, and globals()['defaultDictOfLists'] raises a KeyError.

Is there a way to fix it? It would clarify my code a lot and speed up the coding process as well.


Edit

I'm not using defaultdict(list) because this dictionary is passed to a Django template and those don't handle defaultdicts very well for some reason. So I'd have to convert this defaultdict back to a regular dict, which takes O(n) time, if I recall correctly.

Это было полезно?

Решение

Why don't you just monkeypatch it? You can:

from module import tryAppendingToDict as _tryAppendingToDict

def tryAppendingToDict(key, item, dictionary=defaultDictOfLists):
    return _tryAppendingToDict(dictionary, key, item)

And use this function in the module where defaultDictOfLists is actually defined.

Moreover, I can't see the usefulness of this code, sure you can use defaultdict, but you can also use dictionaries' setdefault method. It will reduce your dictionary insertions to one line, turning tryAppendingToDict() useless:

>>>d={}
>>>d.setdefault('key',['value'])
>>>d
{'key': ['value']}

Другие советы

If you want to have group items in lists that are values of dictionary, you can use collections.defaultdict:

import collections

data = collections.defaultdict(list)
raw = [(i % 3, i) for i in range(10)] # sample data

for key, value in raw:
    data[key].append(value)

Without much trouble you get what you want:

In [10]: data
Out[10]: defaultdict(<type 'list'>, {0: [0, 3, 6, 9], 1: [1, 4, 7], 2: [2, 5, 8]})

see http://docs.python.org/2/library/collections.html#collections.defaultdict for more information and use cases.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top