index = {}

with open('zen.txt', encoding='utf-8') as fp:
    for line_no, line in enumerate(fp, 1):
        for match in WORD_RE.finditer(line):
            word = match.group()
            column_no = match.start() + 1
            location = (line_no, column_no)
            
            #ugly implement
            occurrences = index.get(word, []) # <1>
            occurrences.append(location)      # <2>
            index[word] = occurrences         # <3>

for word in sorted(index, key=str.upper):  # <4>
    print(word, index[word])

"""
Explanation: without use any default value
End of explanation
"""


index = {}

with open('zen.txt', encoding='utf-8') as fp:
    for line_no, line in enumerate(fp, 1):
        for match in WORD_RE.finditer(line):
            word = match.group()
            column_no = match.start() + 1
            location = (line_no, column_no)
            
            index.setdefault(word, []).append(location) # <1>

"""
Explanation: handling missing keys with setdefault
End of explanation
"""


from collections import defaultdict

# create defaultdict with list constructor as default_factory
index = defaultdict(list)

with open('zen.txt', encoding='utf-8') as fp:
    for line_no, line in enumerate(fp, 1):
        for match in WORD_RE.finditer(line):
            word = match.group()
            column_no = match.start() + 1
            location = (line_no, column_no)
            
            index[word].append(location) # <1>

dd = defaultdict(list)

dd['abc']

dd.get('bbb') ## None if useing .get() function

dd

"""
Explanation: my_dict.setdefault(key, []).append(new_value)
same as
if key not in my_dict:
    my_dict[key] = []
my_dict[key].append(new_value)
use defaultdict
End of explanation
"""


