Test that all Python keywords are mentioned in a dictionary's values I have a dict of categories of Python keywords, with lists of keywords as the values:

Keywords_33=[('File_2', ['with', 'as']),
             ('Module_2', ['from', 'import']),
             ('Constant_3', {'bool': ['False', 'True'],
                             'none': ['None']}),
             ('Operator_4', {'boolean_operation': {'or', 'and', 'not'},
                             'comparison': {'is'}}),
             ('Container_operation_2', ['in', 'del']),
             ('Klass_1', ['class']),
             ('Function_7',['lambda', 'def', 'pass',
                            'global', 'nonlocal',
                            'return', 'yield']),
             ('Repetition_4', ['while', 'for', 'continue', 'break']),
             ('Condition_3', ['if', 'elif', 'else']),
             ('Debug_2', ['assert', 'raise']),
             ('Exception_3', ['try', 'except', 'finally'])]


I want to ensure that every keyword is in a category.  This code does that:

from keyword import kwlist
s = str(Keywords_33)
intersection_with_kwlist = [keyword for keyword in kwlist if keyword not in s]
print(intersection_with_kwlist)


Expected (and actual) output:

[]


This indicates that no keywords are missing from Keywords_33.

Can I make this code more elegant?
I'd personally use a generic function to flatten your datatype.


If an item in your collection in collections.Iterable then you will want to recurse through it.
If it's not you will want to yield it.
If it's a str or bytes you'll want to yield it, however this can change. And so you'll want to pass a tuple of these wanted types.
You probably want to only go through dictionary values as opposed to keys. And so you should pass a function to handle dictionaries.


And so I'd make:

def flatten(obj, dict_handle=dict.keys, wanted=(str, bytes)):
    def inner(obj):
        if isinstance(obj, dict):
            obj = dict_handle(obj)
        for el in obj:
            if isinstance(el, collections.Iterable) and not isinstance(el, wanted):
                yield from inner(el)
            else:
                yield el
    return inner(obj)


From this your code becomes:

from keyword import kwlist
import collections

unknown = set(kwlist) - set(flatten(Keywords_33, dict_handle=dict.values))
print(unknown)


If you don't want to remove 'File_2' from kwlist, then you can always change Keywords_33 to a dictionary:

unknown = set(kwlist) - set(flatten(dict(Keywords_33), dict_handle=dict.values))
print(unknown)