2

I categorized keywords as following nest list,

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 intent to confirm every keyword in place by category without any left. The most convenient I consider is to convert Keywords_33 to string firstly.

from keyword import kwlist
In [55]: print(kwlist)
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
In [54]: from keyword import kwlist
...: s = str(Keywords_33)
...: [keyword for keyword in kwlist if keyword not in s]
...:
Out[54]: []
# It indicate no keyword left

How to accomplish such a task elegantly?

2 Answers2

3

Relying on the string representation of your nested list of dicts/list is a bit hazardous because you could match words/substrings you don't want (example elif contains if so if your list contains elif, it will match if as well. Some clever re.findall could work, extracting text between quotes, but that's still a hack.

Instead, you could create a list of the values of the dicts or the lists (depending on the type) which yields:

['with', 'as', 'from', 'import', ['None'], ['False', 'True'], {'and', 'or', 'not'}, {'is'}, 'in', 'del', 'class', 'lambda', 'def', 'pass', 'global', 'nonlocal', 'return', 'yield', 'while', 'for', 'continue', 'break', 'if', 'elif', 'else', 'assert', 'raise', 'try', 'except', 'finally']

then use a flatten recipe on an irregular list of items (Flatten (an irregular) list of lists), convert to set and substract both ways / intersect whatever:

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'])]

import collections
from keyword import kwlist

def flatten(l):
    for el in l:
        if isinstance(el, collections.Iterable) and not isinstance(el, (str, bytes)):
            yield from flatten(el)
        else:
            yield el

my_keywords = set(flatten(x for _,l in Keywords_33 for x in (l if isinstance(l,list) else l.values())))

in that case set(kwlist) == my_keywords

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
0
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'])]

kwlist = ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def',
      'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import',
      'in','is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while',
      'with', 'yield']

if __name__ == '__main__':
    result = []
    for kw in kwlist:
        for key in Keywords_33:
            if isinstance(key[1], list):
                for i in key[1]:
                    if kw == i:
                        result.append(i)
            elif isinstance(key[1], dict):
                for value in key[1].values():
                    for j in value:
                        if kw == j:
                            result.append(j)

    print(result)

i distinguish, if the second element is a list or a dictionary. (Attention, in this case it works, because every tuple contains exactly two elements). In the list case, i can easily iterate through and compare if the element is in the kwlist. In case of dictionary, i can iterate through the values of the dictionary and compare, if the value is in kwlist

bierschi
  • 322
  • 3
  • 11