jeffsia
jeffsia

Reputation: 369

'NoneType' object has no attribute 'append'

I have two lists that I'm merging into a dictionary

keys = ['p2p', 'groupchat']
tests_available = ['p2p_1', 'p2p_2', 'p2p_3', 'groupchat_1', 'groupchat_2']

The expected output will be something like

{'p2p': ['p2p_1', 'p2p_2', 'p2p_3'], 'groupchat': ['groupchat_1', 'groupchat_2']
}

My code to create the dictionary is below.

out = {}
out = dict.fromkeys(keys)

for tests in tests_available:
    if tests.split('_')[0] in keys:
        key = tests.split('_')[0]
        out[key].append(tests)

However, it is throwing the error 'NoneType' object has no attribute 'append' when it is trying to append the values to the key. Can anyone help me identify what is wrong in my code?

Upvotes: 0

Views: 4388

Answers (3)

Eugene Yarmash
Eugene Yarmash

Reputation: 149776

For a small number of keys/tests a dictionary comprehension would work as well:

keys = ['p2p', 'groupchat']
tests_available = ['p2p_1', 'p2p_2', 'p2p_3', 'groupchat_1', 'groupchat_2']
out = {k: [v for v in tests_available if v.startswith(k)] for k in keys}

Demo:

>>> out
{'groupchat': ['groupchat_1', 'groupchat_2'], 'p2p': ['p2p_1', 'p2p_2', 'p2p_3']}

Upvotes: 1

EdChum
EdChum

Reputation: 394031

If you use a defaultdict then the append call will work as the value type defaults to a list:

In [269]:
from collections import defaultdict
keys = ['p2p', 'groupchat']
tests_available = ['p2p_1', 'p2p_2', 'p2p_3', 'groupchat_1', 'groupchat_2']
d = defaultdict(list)
for test in tests_available:
    k = test.split('_')[0]
    if k in keys:
        d[k].append(test)
d.items()

Out[269]:
dict_items([('p2p', ['p2p_1', 'p2p_2', 'p2p_3']), ('groupchat', ['groupchat_1', 'groupchat_2'])])

See the docs: https://docs.python.org/2/library/collections.html#defaultdict-examples

Upvotes: 4

Padraic Cunningham
Padraic Cunningham

Reputation: 180401

Your values are set to None in fromkeys unless you explicitly set a value:

fromkeys(seq[, value])

Create a new dictionary with keys from seq and values set to value. fromkeys() is a class method that returns a new dictionary. value defaults to None.

In your case you need to create lists as values for each key:

d = {k:[] for k in keys}

You can also do your if check using the dict:

d = {k:[] for k in keys}

for test in tests_available:
    k = tests.split('_', 1)[0]
    if k in d:
        d[k].append(test)

You can pass a value to use to fromkeys but it has to be immutable or you will be sharing the same object among all keys.

Upvotes: 3

Related Questions