делая
contact = {
"id":"",
"email":""
}
вне цикла, у вас есть один экземпляр объекта. Вы просто изменяете один и тот же экземпляр снова и снова (result.append
не создает копию словаря, только сохраняет ссылку)
Одним из решений является определение его внутри цикла или создание копии
for line in source:
email = re.search(r'[\w\.-]+@[\w\.-]+', line)
contact = {} # create a new, empty instance
contact['email'] = email.group(0)
...
обратите внимание, что нет необходимости определять словарь с ключами и пустыми значениями, так как вы все равно перезаписываете их. Определите это пустым.
Другая альтернатива - вообще не использовать contact
и создавать словарь на лету, используя буквальную форму при добавлении в список:
results.append({"email":email.group(0), "id":p.group(0)})
вы также можете вообще пропустить цикл и записать его в одну строку, используя понимание списка:
results = [{"email":re.search(r'[\w\.-]+@[\w\.-]+', line).group(0), "id":re.search(r'\d\d\d\d\d', line).group(0)} for line in source]
Единственная проблема здесь в том, что вы не можете обрабатывать случаи, когда нет совпадения, по крайней мере, легко.