|
Вспомогательные функции задачника
Описанные на данной странице функции и класс Node будут доступны в программе, если к ней подключен модуль
pt4.py (данный модуль входит в состав дистрибутива задачника Programming Taskbook и автоматически
подключается к любому проекту-заготовке, созданному для выполнения задания на языке Python).
Инициализация заданий, ввод-вывод данных
task(name)
Функция инициализирует задание с именем name (обязательный строковый параметр). Она должна
вызываться в начале программы, выполняющей это задание (до вызова функций ввода-вывода get и put).
Если в программе, подключившей модуль pt4, не указана функция task, то при запуске программы
в окне интерпретатора Python будет выведено сообщение «Не вызвана функция task с именем задания».
Строковый параметр name должен включать имя группы заданий и порядковый номер в пределах группы (например, "Begin3" ).
Регистр букв в имени группы может быть произвольным. Если указана неверная группа, то программа выведет
сообщение об ошибке «Указана неверная тема задания»
(список всех доступных групп можно получить с помощью программных модулей PT4Demo и PT4Load).
Если указан недопустимый номер задания, то программа выведет сообщение,
в котором будет указан диапазон допустимых номеров для данной группы. Если после имени задания в параметре name
указан суффикс «?» (например, "Begin3?" ), то программа будет работать в демонстрационном режиме.
Функция task может также использоваться для генерации и вывода на экран html-страницы с текстом задания или группы заданий.
Для этого необходимо указать в качестве параметра name имя конкретного задания или группы заданий и суффикс «#»,
например, "Begin3#" или "Begin#" .
Начиная с версии 4.13, задачник обеспечивает автоматическое тестирование программы на нескольких
наборах исходных данных при ее однократном запуске. Для отключения этой возможности достаточно
указать в параметре Name после имени задания суффикс «!» (например, "Begin3!" );
в этом случае при запуске программы она будет протестирована на единственном наборе исходных данных,
и для проверки правильности решения программу потребуется запустить несколько раз (как в предыдущих версиях
задачника).
Если функция task вызывается в программе несколько раз, то все последующие ее вызовы игнорируются.
Исключением является ситуация, когда функция используется для генерации html-страницы с описанием нескольких
заданий или групп заданий; в этом случае учитываются все вызовы данной функции.
Начиная с версии 4.12, параметр name может содержать суффикс «_ru»
или «_en», позволяющий явным образом задать язык интерфейса
(русский или английский соответственно) для окна задачника и выполняемого задания.
В версиях 4.124.14 специальные суффиксы «?», «#» и «!» должны указываться перед данным суффиксом,
например, "Begin3#_en" ; начиная с версии 4.15, суффиксы могут указываться в любом порядке.
В случае нескольких вызовов функции task (для генерации
html-страницы) учитывается только суффикс, указанный при первом вызове функции.
При отсутствии суффикса используется язык интерфейса, определенный в качестве основного для данного рабочего каталога
(в универсальном варианте задачника основной язык интерфейса можно настроить с помощью программного модуля PT4Load,
используя его контекстное меню).
get()
get_bool()
get_int()
get_float()
get_str()
get_Node()
Функции обеспечивают ввод исходных данных в программу, выполняющую учебное задание. Они должны вызываться
после вызова функции task; в случае их вызова до функции task программа выведет сообщение об ошибке
«В начале программы не вызвана функция task с именем задания».
Каждый вызов функции возвращает очередной
элемент исходных данных. Функция get позволяет ввести элемент данных любого типа (логического, целого,
вещественного, строкового или класса Node, описываемого ниже).
Прочие функции предназначены для ввода даннных определенного типа:
get_bool логического, get_int целого, get_float вещественного, get_str строкового,
get_Node объекта типа Node
(символы в языке Python не являются особым типом данных, поэтому для них не предусмотрено
специальной функции ввода).
Особенность «специализированных»
функций get_bool, get_int, get_float, get_str и get_Node по сравнению с «универсальной»
функцией get состоит в том, что если
вызванная «специализированная» функция не соответствует типу очередного элемента исходных данных, то
выводится сообщение об ошибке «Неверно указан тип при вводе исходных данных»
(такое сообщение будет выведено, например, если очередной элемент данных является символом,
а для его ввода используется функция get_int). Таким образом, применение «специализированных»
функций позволяет задачнику выявить такие ошибки ввода, как, например,
ошибки, связанные с неверным порядком чтения исходных данных. «Универсальная»
функция get больше соответствует идеологии языка Python, однако при ее использовании
теряется часть возможностей задачника, связанных с контролем правильности ввода исходных данных.
При попытке ввести больше исходных данных, чем это предусмотрено в задании, выводится сообщение
об ошибке «Попытка ввести лишние исходные данные». Если исходные данные, необходимые
для решения задания, введены не полностью, то выводится сообщение «Введены не все требуемые исходные данные».
get2()
get3()
get4()
get5()
get_list(n = -1)
get_matr(m = -1, n = -1)
Эти функции появились в версии задачника 4.19. Они упрощают организацию ввода нескольких скалярных данных, а также
наборов данных, которые следует сохранять в списке или в матрице (списке списков).
Функции get2, get3, get4, get5 обеспечивают последовательный вызов 2, 3, 4 и 5 функций get и возвращают
кортеж, содержащий все введенные данные. Например, для ввода трех исходных данных и записи их в переменные a, b, c
достаточно использовать оператор
a, b, c = get3()
Функция get_list без параметров вначале считывает размер n вводимого списка (с помощью функции get_int), после чего
считывает n последующих элементов исходных данных (с помощью функции get) и добавляет их в список,
который возвращается как результат работы этой функции.
Если при вызове функции get_list явно указан неотрицательный целочисленный параметр n, то он считается размером списка;
в этом случае функция вводит только элементы списка. Отрицательные значения параметра n означают, что перед вводом
элементов необходимо ввести размер списка (таким образом, в случае отрицательного параметра функция ведет себя так же,
как при вызове без параметров). Если параметр не является целым числом, то возбуждается исключение.
Функция get_matr без параметров вначале считывает размеры m и n вводимой матрицы
(с помощью двух функций get_int), после чего
считывает m*n последующих элементов исходных данных (с помощью функции get) и добавляет их в список,
который возвращается как результат работы этой функции. Предполагается, что значение m определяет число строк и соответствует
первому индексу полученной матрицы, а значение n определяет число столбцов и соответствует второму индексу матрицы.
Предполагается также, что ввод элементов матрицы осуществляется по строкам. Результирующая матрица представляет собой
список списков. Таким образом, оператор a = get_matr() эквивалентен следующей последовательности операторов:
m, n = get_int(), get_int()
a = [[get() for j in range(n)] for i in range(m)]
Если при вызове функции get_matr явно указаны два неотрицательных целочисленных параметра m и n,
то они считаются размерами матрицы; в этом случае функция вводит только элементы матрицы.
Если второй параметр (n) не указан или является отрицательным, а первый параметр (m) указан и является неотрицательным,
то считается, что вводимая матрица является квадратной матрицей порядка m; в этом случае функция также вводит только
элементы матрицы. Таким образом, для ввода квадратной матрицы (в предположении, что перед ее элементами задается
единственное значение порядок матрицы) достаточно выполнить следующий оператор:
a = get_matr(get())
Если первый параметр функции get_matr является отрицательным, то функция работает так же,
как при вызове без параметров.
Если параметры функции не являются целыми, то возбуждается исключение.
put(a, ...)
Функция put обеспечивает вывод на экран результирующих данных, найденных программой,
и их сравнение с контрольными данными (т. е. с правильным решением). Как и функции группы get,
эта функция должна вызываться после вызова функции task; в противном случае ее вызов приводит к сообщению об ошибке
«В начале программы не вызвана функция task с именем задания».
В функции put можно указывать один или более параметров. В качестве любого параметра можно указать
переменную или выражение типа bool, int, float, str, Node, а также кортеж (tuple) или список (list) элементов этих типов.
Указание кортежа или списка приводит к тому, что в задачник последовательно пересылаются все элементы
этого кортежа или списка.
В качестве параметров метода put
можно указывать не только переменные, но и выражения (в частности, константы
соответствующего типа, а также пустой объект None.
Заметим, что пустые объекты, как и объекты типа Node, требуется
выводить только в заданиях групп Dynamic
и Tree и их аналогов GCDyn и GCTree.
При попытке указания данных других типов
программа генерирует стандартное исключение ValueError с сообщением об ошибке
«the put function has an argument of invalid type» (сообщение на английском языке означает, что
данная ошибка обнаружена без обращения к ядру задачника).
Тип параметра должен не только быть допустимым, но и соответствовать типу
очередного элемента результирующих данных; в противном случае выводится
сообщение об ошибке «Неверно указан тип при выводе результатов».
При вызове функции put задачник осуществляет контроль
за соответствием количества требуемых и выведенных результирующих данных. Если программа выведет
недостаточное или избыточное количество результирующих данных, то после проверки этих данных появится сообщение
«Выведены не все результирующие данные» или, соответственно, «Попытка вывести лишние результирующие данные».
Класс Node
# Конструкторы:
Node(data = 0, next = None, prev = None)
Node.for_tree(data = 0, left = None, right = None, parent = None)
# Свойства (доступны для чтения и для записи):
Data
Next
Prev
Left
Right
Parent
# Метод, освобождающий неуправляемые ресурсы, используемые объектом Node:
dispose()
Класс Node используется в заданиях групп Dynamic
и Tree и их аналогов GCDyn и GCTree. В заданиях на
стеки и очереди (Dynamic1Dynamic28) при работе с объектами типа Node
используются только свойства Data и Next; в заданиях на двусвязные списки
(Dynamic29Dynamic80) используются свойства Data, Next и Prev. В большинстве заданий на
бинарные деревья (группа Tree) используются свойства Data, Left и Right;
в заданиях на обработку бинарных деревьев с обратной связью
(Tree48Tree56 и Tree70Tree71) дополнительно используется свойство Parent.
Варианты конструктора класса Node (в том числе варианты функции Node.for_tree)
позволяют задавать значения требуемых свойств при создании
объекта; прочие свойства инициализируются нулевыми значениями
(числом 0 для свойства Data, пустым объектом None для остальных свойств).
Следует обратить внимание на то, что при завершении работы с объектом типа Node требуется вызвать
его метод dispose, освобождающий неуправляемые ресурсы, выделенные для этого
объекта (исключение делается только для тех объектов, которые передаются обратно
задачнику в качестве результирующих данных). Если в задании требуется вызвать
метод dispose для некоторых объектов, но этот вызов не выполняется, то при запуске
программы выводится сообщение об ошибке «Не вызван метод dispose для
объекта типа Node». При выполнении заданий групп GCDyn и GCTree, появившихся в версии 4.15,
использовать метод dispose не требуется.
Все исходные и результирующие данные-ссылки в заданиях группы Dynamic
имеют тип Node; их ввод и вывод должен осуществляться с помощью описанных выше функций
get (или get_Node) и put.
Вывод отладочной информации
С помощью описываемых далее средств можно выводить отладочную информацию
непосредственно в окно задачника (в специальный раздел отладки).
Следует заметить, что при использовании языка Python имеется и другой способ
вывода отладочной информации, основанный на применении стандартной инструкции print.
Отличие заключается в размещении информации: инструкция print
выводит данные в окне интерпретатора Python, тогда как описываемые ниже
средства (функции show и show_line) в окно задачника.
Начиная с версии 4.22, в раздел отладки можно выводить текстовые данные,
содержащие любые символы Юникода.
show(a, ...)
Отображает элемент данных в разделе отладки окна задачника. В качестве параметра a можно указывать элемент данных
любого типа; этот элемент будет автоматически преобразован к своему строковому представлению.
Если текущая экранная строка в разделе отладки уже содержит некоторый текст, то
строка a снабжается начальным пробелом и приписывается к предшествующему тексту,
за исключением случая, когда при таком приписывании размер
полученного текста превысит ширину области данных (равную 80 символам).
В последнем случае вывод строки a осуществляется с начала
следующей экранной строки; если же и в этой ситуации строка a превысит
ширину области данных, то строка a будет выведена на нескольких
экранных строках, причем разрывы текста будут выполняться по
пробельным символам строки a, а при отсутствии пробелов при
достижении очередного фрагмента строки длины, равной 80.
Строковый параметр a может содержать явные команды перехода на новую
экранную строку. В качестве таких команд можно использовать или
символ с кодом 13 (chr(13) или "\r" «возврат каретки»),
или символ с кодом 10 (chr(10) или "\n" «переход на новую
строку»), или их комбинацию в
указанном порядке (chr(13) + chr(10) или "\r\n" ).
С помощью операции + можно выводить
в раздел отладки данные вместе с предшествующим комментарием, однако в этом случае следует
выполнять явное преобразование данных к строковому представлению, например:
show("a = " + str(a))
Начиная с версии 4.14, в функции show можно указывать произвольное количество параметров. Параметрами могут быть
элементы данных любого скалярного типа, а также списки и кортежи (для которых выводятся все входящие в них элементы).
Минимальная ширина поля вывода устанавливается функцией set_width(w),
представление вещественных чисел определяется функцией set_precision(d) (обе функции описываются ниже).
Для остальных типов данных используются их стандартные строковые представления (как и в реализации функции show
для предыдущих версий задачника). Числовые данные выравниваются по правой границе, прочие данные по левой.
В версии 4.19 реализация функции show изменена таким образом, чтобы обеспечивать форматированный вывод
структур данных, в том числе вложенных. При оформлении выводимых структур используются стандартные обозначения,
принятые в языке Python: кортежи (tuple) обрамляются круглыми скобками, списки (list) квадратными,
множества (set) и словари (dict) обрамляются фигурными скобками, ключи (key) и значения (value) элементов
словарей разделяются двоеточием. Кроме того, для обеспечения большей наглядности (хотя и в отступление
от правил языка Python) каждый элемент словаря заключается в круглые скобки. Элементы структур разделяются запятыми
(за исключением элементов, которые сами являются множествами, списками или словарями,
после которых запятая не указывается, поскольку
такие элементы разделяются разрывами строк см. далее).
После вывода любой структруры, имеющей переменное число элементов (т. е. множества, списка или словаря),
выполняется автоматический переход на следующую экранную строку в разделе отладки.
При наличии нескольких вложенных структур уровень их вложенности оформляется с помощью дополнительных отступов.
Ниже приводятся примеры использования функции show для вывода различных структур данных.
Фрагмент программы, обеспечивающий отладочный вывод, имеет следующий вид
(было использовано задание Matrix80, в котором дается вещественная квадратная матрица):
task("Matrix80")
show_line("Матрица (список списков) вещественных чисел (width = 5):")
a = get_matr(get())
set_width(5)
show_line(a)
show_line("Словарь строковых кортежей (width = 0):")
b1 = {1:("abc","d","efg"), 2:("123","456","7"), 22:("**","!!")}
set_width(0)
show_line(b1)
show_line("Словарь строковых списков (width = 3):")
b2 = {1:["abc","d","efg"], 2:["123","456","7"], 22:["**","!!"]}
set_width(3)
show_line(b2)
show_line("Список списков, содержащих числовые кортежи (width = 2):")
c1 = [[(1,2,3),(4,5,6)], [(7,8,9),(10,11,12)], [(13,14,15), (16,17,18)]]
set_width(2)
show_line(c1)
show_line("Список списков, содержащих числовые списки (width = 2):")
с2 = [[[1,2,3],[4,5,6]], [[7,8,9],[10,11,12]], [[13,14,15], [16,17,18]]]
show_line(с2)
В приведенном далее образце содержимого раздела отладки следует обратить
внимание на то, что при выводе скалярных элементов или элементов-кортежей
они разделяются запятыми, тогда как после каждого элемента-списка
выполняется переход на новую строку. Кроме того, следует обратить внимание
на использование отступов при выводе многомерных списков, а также на
настройку ширины области вывода с помощью функции set_width.
1> Матрица (список списков) вещественных чисел (width = 5):
2> [ [ 0.14 , 3.21 , 7.86 , 1.73 , 9.20 ]
3> [ 9.53 , 6.22 , 4.05 , 9.19 , 4.77 ]
4> [ 0.24 , 5.84 , 3.35 , 8.84 , 1.32 ]
5> [ 5.54 , 1.75 , 7.70 , 7.30 , 8.09 ]
6> [ 0.97 , 4.31 , 0.90 , 3.76 , 6.06 ]
7> ]
8> Словарь строковых кортежей (width = 0):
9> { ( 1 : ( abc , d , efg ) ) , ( 2 : ( 123 , 456 , 7 ) ) , ( 22 : ( ** , !! ) ) }
10> Словарь строковых списков (width = 3):
11> { ( 1 : [ abc , d , efg ]
12> ) ( 2 : [ 123 , 456 , 7 ]
13> ) ( 22 : [ ** , !! ]
14> ) }
15> Список списков, содержащих числовые кортежи (width = 2):
16> [ [ ( 1 , 2 , 3 ) , ( 4 , 5 , 6 ) ]
17> [ ( 7 , 8 , 9 ) , ( 10 , 11 , 12 ) ]
18> [ ( 13 , 14 , 15 ) , ( 16 , 17 , 18 ) ]
19> ]
20> Список списков, содержащих числовые списки (width = 2):
21> [ [ [ 1 , 2 , 3 ]
22> [ 4 , 5 , 6 ]
23> ]
24> [ [ 7 , 8 , 9 ]
25> [ 10 , 11 , 12 ]
26> ]
27> [ [ 13 , 14 , 15 ]
28> [ 16 , 17 , 18 ]
29> ]
30> ]
show_line(a, ...)
Модификация ранее описанной функции show; после вывода элемента данных a в раздел отладки
данная функция дополнительно осуществляет автоматический переход на следующую экранную строку.
Может вызываться без параметров, в этом случае просто выполняет переход на следующую строку.
Начиная с версии 4.19, функция show_line выполняет дополнительный переход на следующую строку только в случае,
если последним выводимым элементом данных не является структура переменной длины (список, множество или словарь),
поскольку после вывода подобных структур всегда выполняется переход на новую строку.
set_width(w)
Определена в задачнике, начиная с версии 4.14. Задает минимальную ширину w (w >= 0) поля вывода для элементов
данных, выводимых функциями show и show_line (за исключением особых элементов chr(10) , chr(13) и
chr(13) + chr(10) ); по умолчанию минимальная ширина полагается равной 0.
Действие функции распространяется на все последующие вызовы функций show и show_line.
Числовые данные выравниваются по правой границе, прочие данные по левой.
set_precision(d)
Определена в задачнике, начиная с версии 4.14. Устанавливает количество d дробных знаков при выводе вещественных чисел
(при d = 0 используется формат с плавающей точкой); по умолчанию d = 2.
Действие функции распространяется на все последующие вызовы функций show и show_line.
hide_task()
Вызов данной функции обеспечивает автоматическое скрытие всех разделов окна
задачника, кроме раздела отладки. Если раздел отладки в окне задачника
не отображается (в частности, если программа запущена в
демонстрационном режиме), то вызов функции hide_task игнорируется.
Игнорируются также все повторные вызовы данной функции.
Скрыть/восстановить основные разделы окна
задачника после его отображения на экране можно также с помощью клавиши
пробела или соответствующей команды контекстного меню раздела отладки.
|