• Информационные строки, которые интерпретатор Python выводит при запуске, я опустил ради экономии места.
• Все примеры из этой книги я запускал под управлением Python 3.1; результаты работы примеров во всех версиях линейки 3.X должны быть одинаковыми (разумеется, исключая непредвиденные случаи внесения существенных изменений в Python).
• Большая часть примеров в этой книге, за исключением некоторых из них, демонстрирующих приемы системного программирования и интеграции с программным кодом на языке C, выполнялись в ОС Windows 7. Однако, благодаря переносимости Python, не имеет значения, в какой операционной системе будут опробоваться примеры, если иное не указано явно.
Если прежде вам не доводилось выполнять программный код на языке Python подобным способом, тогда обращайтесь за справочной информацией к вводным материалам, таким как книга «Изучаем Python». Далее в этой главе я сделаю несколько замечаний, касающихся запуска программного кода, хранящегося в файлах сценариев.
База данных в виде списка
К настоящему моменту мы всего создали всего лишь две переменных, но не базу данных. Чтобы объединить информацию о Бобе и Сью, мы могли бы просто включить ее в другой список:
>>> people = [bob, sue] # ссылки в списке списков
>>> for person in people: print(person)
[‘Bob Smith’, 42, 30000, ‘software’]
[‘Sue Jones’, 45, 50000.0, ‘hardware’]
Теперь нашу базу данных представляет список people. Мы можем извлекать из него отдельные записи в соответствии с их позициями в списке и обрабатывать их в цикле:
>>> people[1][0]
‘Sue Jones’
>>> for person in people:
print(person[0].split()[-1]) # вывести фамилию
person[2] *= 1.20 # увеличить оклад на 20%
Smith
Jones
>>> for person in people: print(person[2]) # проверить новый размер оклада
36000.0
60000.0
Теперь, когда у нас имеется список, мы можем организовать выборку значений полей из записей с помощью более мощных инструментов выполнения итераций, присутствующих в языке Python, таких как генераторы списков, функция map и выражения-генераторы:
>>> pays = [person[2] for person in people] # выбрать все оклады >>> pays
[36000.0, 60000.0]
>>> pays = map((lambda x: x[2]), people) # то же самое (в версии 3.X
>>> list(pays) # функция map возвращает генератор)
[36000.0, 60000.0]
>>> sum(person[2] for person in people) # выражение-генератор,
96000.0 # sum - встроенная функция
Для добавления новых записей в базу данных вполне достаточно использовать обычные операции над списками, такие как append и extend:
>>> people.append(['Tom', 50, 0, None])
>>> len(people)
3
>>> people[-1][0]
‘Tom’
Списки неплохо подходят для реализации нашей базы данных, и их возможностей вполне достаточно для некоторых программ, но они страдают рядом существенных недостатков. Во-первых, информация о Бобе и Сью в настоящий момент хранится в виде объектов в оперативной памяти, и она будет утеряна сразу после завершения работы интерпретатора Python. Во-вторых, всякий раз, когда потребуется извлечь фамилию человека или повысить ему оклад, нам придется повторно вводить программный код, который мы только что видели. Это может вызвать определенные проблемы, если когда-нибудь поменяется алгоритм выполнения этих операций, - нам может потребоваться изменить наш программный код во многих местах. Мы вернемся к этим проблемам через несколько минут.
Обращение к полям по именам
Самый, пожалуй, существенный недостаток при использовании списков заключается в необходимости запоминать позиции полей: как иначе можно утверждать, что программный код, обращающийся к элементу записи с таинственным индексом 2, извлекает размер оклада? С точки зрения очевидности программного кода было бы лучше, если бы можно было присвоить каждому полю осмысленное имя.
Мы могли бы связать имена с позициями полей в записи, используя встроенную функцию range, которая генерирует набор последовательных целых чисел при использовании в контексте итераций (таких как операция присваивания последовательности ниже):
>>> NAME, AGE, PAY = range(3) # 0, 1 и 2
>>> bob = ['Bob Smith’, 42, 10000]
>>> bob[NAME]
‘Bob Smith’
>>> PAY, bob[PAY]
(2, 10000)
Это решает проблему читаемости программного кода: три имени переменных, состоящих из заглавных символов, по сути, превратились в имена полей. Однако такое решение делает программный код зависящим от инструкции присваивания позиций именам полей, - мы должны помнить о необходимости обновлять ее при любом изменении структуры записи. Поскольку имена полей и записи никак не связаны между собой, они могут перестать соответствовать друг другу, и тогда возникнет необходимость вмешательства в программный код.