Однако имейте в виду, что при такой реализации строковые значения, вводимые в поля ввода, должны заключаться в кавычки, так как содержимое всех полей ввода, кроме поля key (ключ), интерпретируется как программный код на языке Python. Фактически, чтобы определить
новое значение, в поле ввода можно ввести произвольное выражение на языке Python. Например, если в поле name (имя) ввести выражение Tom'*3, после щелчка на кнопке Update (Изменить) в записи будет сохранено имя TomTomTom. Чтобы убедиться в этом - извлеките запись из хранилища.
Несмотря на наличие графического интерфейса, позволяющего просматривать и изменять записи, мы по-прежнему можем проконтролировать свои действия, открыв и проверив файл хранилища в интерактивном режиме или запустив сценарий, такой как
...\PP4E\Preview> python dump_db_classes.py
sue =>
Sue Jones 50000.0 bill => bill 9999 nobody =>
John Doh None tomtom =>
Tom Tom 40000 tom =>
Tom Doe 90000 bob =>
Bob Smith 30000 peg =>
1 4 Smith Doe
Пути усовершенствования
Построенный нами графический интерфейс справляется со своей задачей, тем не менее в него можно внести множество разных усовершенствований:
• На настоящий момент графический интерфейс представляет собой набор функций, использующих глобальный список полей (entries) ввода и глобальное хранилище (db). Вместо этого мы могли бы передать db в вызов функции makeWidgets и организовать передачу обоих этих объектов обработчикам событий в виде аргументов, воспользовавшись приемом с инструкцией lambda из предыдущего раздела. Хотя для таких маленьких сценариев это и не так важно, стоит иметь в виду, что явное определение подобных внешних зависимостей делает программный код более простым для понимания и повторного использования в других контекстах.
• Этот графический интерфейс можно было бы реализовать в виде класса, чтобы обеспечить поддержку возможности специализации и присоединения к другим графическим интерфейсам (глобальные переменные в этом случае могли бы стать атрибутами экземпляра), хотя повторное использование столь специфического интерфейса маловероятно.
• Полезнее было бы передавать функциям в виде параметра кортеж fieldnames, чтобы в будущем их можно было использовать с другими типами записей. Программный код в конце сценария также можно было бы оформить в виде функции, принимающей имя файла хранилища, а в функцию updateRecord можно было бы передавать функцию, создающую новую запись, чтобы она могла сохранять не только экземпляры класса Person. Эти усовершенствования выходят далеко за рамки данного краткого обзора, но их реализация была бы для вас неплохим упражнением. Позднее я познакомлю вас с еще одним дополнительным примером, входящим в комплект примеров к книге, PyForm, в котором используется иной подход к созданию универсальных форм ввода.
• Чтобы сделать этот графический интерфейс более дружественным по отношению к пользователю, можно было бы добавить окно со списком всех ключей, имеющихся в базе данных, и тем самым упростить просмотр содержимого базы данных. Полезно было бы предусмотреть проверку данных перед сохранением, а кроме того, легко можно было бы добавить клавиши Delete (Удалить) и CLear (Очистить). Тот факт, что введенные данные интерпретируются как программный код на языке Python, может доставить массу беспокойств - реализация простейшей схемы ввода могла бы повысить безопасность. (Я не буду явно предлагать реализовать эти усовершенствования в качестве самостоятельного упражнения, но это было бы полезно.)
• Мы могли бы также реализовать поддержку изменения размеров окна (как мы узнаем позднее, виджеты могут растягиваться и сжиматься вместе с окном) и предоставить возможность вызова методов, которыми обладают сохраняемые экземпляры классов (в том смысле, что графический интерфейс позволяет изменить значение поля pay, но не позволяет вызвать метод giveRaise).
• Если бы мы планировали распространять этот графический интерфейс, мы могли бы упаковать его в самостоятельную выполняемую программу -
Я оставлю все эти расширения для дальнейшего обдумывания и вернусь к некоторым из них далее в этой книге.