Если же возникнет необходимость последовательно обойти все записи в базе данных, можно воспользоваться итераторами словарей. В последних версиях Python реализован итератор словаря, который на каждой итерации в цикле for воспроизводит по одному ключу (для совместимости с более ранними версиями в циклах for можно также вместо простого имени db использовать явный вызов метода db. keys, но, так как в Python 3 метод keys возвращает генератор, конечный результат будет тот же самый):
>>> for key in db:
print(key, ‘=>', db[key][‘name'])
bob => Bob Smith sue => Sue Jones
>>> for key in db:
print(key, ‘=>', db[key][‘pay'])
bob => 30000 sue => 50000
В процессе обхода доступ к отдельным записям можно получать с использованием операции индексирования по ключу:
>>> for key in db:
print(db[key][‘name'].split()[-1]) db[key][‘pay'] *= 1.10
Smith
Jones
или напрямую, организовав обход значений словаря:
>>> for record in db.values(): print(record[‘pay'])
33000.0
55000.0
>>> x = [db[key][‘name'] for key in db]
>>> x
[‘Bob Smith’, ‘Sue Jones’]
>>> x = [rec[‘name'] for rec in db.values()]
>>> x
[‘Bob Smith’, ‘Sue Jones’]
А чтобы добавить новую запись, достаточно просто выполнить операцию присваивания по новому ключу. В конце концов - это всего лишь словарь:
>>> db[‘tom'] = dict(name='Tom', age=50, job=None, pay=0)
>>>
>>> db[‘tom']
{‘pay’: 0, ‘job’: None, ‘age’: 50, ‘name’: ‘Tom’}
>>> db[‘tom'][‘name']
‘Tom’
>>> list(db.keys())
[‘bob’, ‘sue’, ‘tom’]
>>> len(db)
3
>>> [rec[‘age'] for rec in db.values()]
[42, 45, 50]
>>> [rec[‘name'] for rec in db.values() if rec[‘age'] >= 45] # SQL-подобный [‘Sue Jones’, ‘Tom’] # запрос
Наша база данных по-прежнему является объектом, хранящимся в оперативной памяти. Но, как оказывается, такой формат словаря словарей в точности соответствует формату, который используется системой сохранения объектов в файлах, - модулем shelve (с точки зрения грамматики английского языка этот модуль должен был бы называться
Шаг 2: сохранение записей на длительное время
К настоящему моменту мы остановились на представлении нашей базы данных в виде словаря и попутно рассмотрели некоторые способы реализации структур данных в языке Python. Однако, как уже упоминалось выше, объекты, с которыми мы имели дело до сих пор, - временные объекты; они располагаются в оперативной памяти и исчезают бесследно после завершения работы интерпретатора Python или программы, создавшей их. Чтобы обеспечить долговременное хранение базы данных, ее необходимо сохранить в каком-нибудь файле.
Текстовые файлы
Один из способов обеспечить сохранность данных между запусками программы заключается в сохранении всех данных в простом файле, в виде отформатированного текста. Выработав определенную договоренность о формате представления данных, которая будет использоваться инструментами чтения и записи, мы сможем реализовать любую схему хранения.
Тестовый сценарий создания данных
Чтобы не продолжать дальнейшую работу в интерактивном режиме, напишем сценарий, инициализирующий базу данных, которую требуется сохранить (если вы уже имеете опыт работы с языком Python, то должны знать, что как только вы начинаете писать программный код, занимающий больше одной строки, работа в интерактивном режиме становится утомительной). Сценарий в примере 1.1 создает несколько записей и словарь базы данных, с которыми мы работали до сих пор, но так как он одновременно является модулем, мы сможем импортировать его и избавиться от необходимости всякий раз вводить программный код вручную. В некотором смысле этот модуль и является базой данных, но его реализация не поддерживает возможность изменения данных автоматически или конечным пользователем.
# инициализировать данные для последующего сохранения в файлах
# записи
bob = {‘name’: ‘Bob Smith’, ‘age’: 42, ‘pay’: 30000, ‘job’: ‘dev’}
sue = {‘name’: ‘Sue Jones’, ‘age’: 45, ‘pay’: 40000, ‘job’: ‘hdw’}
tom = {‘name’: ‘Tom’, ‘age’: 50, ‘pay’: 0, ‘job’: None}
# база данных db = {}
db[‘bob’] = bob db[‘sue’] = sue db[‘tom’] = tom
if __name__ == ‘__main__’: # если запускается, как сценарий
for key in db:
print(key, ‘=>\n ‘, db[key])
Как обычно, проверка переменной__name__в конце примера 1.1 возвра
щает true, только если файл был запущен как самостоятельный сценарий, а не был импортирован как модуль. Если запустить пример как самостоятельный сценарий (например, из командной строки, щелчком на ярлыке или из среды IDLE), будет выполнен программный код теста в теле условной инструкции, который выведет содержимое базы данных в поток стандартного вывода (напомню, что функция print использует этот поток по умолчанию).