Инструменту обхода деревьев на основе классов можно найти самые разные применения, однако у нас недостаточно места в книге, чтобы исследовать дополнительные подклассы. Дополнительные примеры реализации клиентов и их использования вы найдете в следующих примерах, входящих в состав пакета, описанного в Предисловии:
• Tools\visitor_collect.py отбирает и/или выводит имена файлов, содержащие искомую строку
• Tools\visitor_poundbang.py замещает пути к каталогам в строках «#!», находящихся в начале файлов сценариев в Unix
• Tools\visitor_cleanpyc.py — переработанная версия сценария удаления файлов с байт-кодом, использующая классы-обходчики
• Tools\visitor_bigpy.py — версия примера «Найди самый большой файл Python», приводившегося в начале главы, использующая классы-обходчики
Реализация большинства из них выглядит почти тривиально, как и реализация visitor_edit.py в примере 6.19, благодаря тому что все детали обхода деревьев каталогов автоматически скрываются за интерфейсом классов-обходчиков. Реализация отбора файлов, например, просто добавляет в список имена файлов, соответствующих критериям поиска, и позволяет переопределить список допустимых расширений имен файлов в каждом экземпляре — она напоминает комбинацию команд find и grep в Unix:
>>> from visitor_collect import CollectVisitor
>>> V = CollectVisitor(‘mimetypes’, testexts=[‘.py’, ‘.pyw’], trace=0)
>>> V.run(r’C:\temp\PP3E\Examples’)
>>> for name in V.matches: print(name) # файлы .py и .pyw со строкой
… # ‘mimetypes’
C:\temp\PP3E\Examples\PP3E\Internet\Email\mailtools\mailParser.py
C:\temp\PP3E\Examples\PP3E\Internet\Email\mailtools\mailSender.py C:\temp\PP3E\Examples\PP3E\Internet\Ftp\mirror\downloadflat.py C:\temp\PP3E\Examples\PP3E\Internet\Ftp\mirror\downloadflat_modular.py C:\temp\PP3E\Examples\PP3E\Internet\Ftp\mirror\ftptools.py
C:\temp\PP3E\Examples\PP3E\Internet\Ftp\mirror\uploadflat.py
C:\temp\PP3E\Examples\PP3E\System\Media\playfile.py
C:\…\PP4E\Tools> visitor_collect.py mimetypes C:\temp\PP3E\Examples # как
# сценарий
Основная логика сценария поиска наибольшего файла также выглядит достаточно просто и напоминает логику сценария в начале главы:
class BigPy(FileVisitor):
def __init__(self, trace=0):
FileVisitor.__init__(self, context=[], trace=trace)
def visitfile(self, filepath):
FileVisitor.visitfile(self, filepath) if filepath.endswith(‘.py’):
self.context.append((os.path.getsize(filepath), filepath))
Пример реализации удаления файлов байт-кода на основе классов- обходчиков также возвращает нас назад, демонстрируя альтернативное решение задачи, с которой мы уже сталкивались выше в этой главе. Это, по сути, тот же самый программный код, но он вызывает функцию os.remove при обнаружении файлов с расширением «.pyc».
Наконец, хотя классы-обходчики действительно являются всего лишь обертками вокруг функции os.walk, тем не менее они автоматизируют рутинные операции, выполняемые при обходе, и обеспечивают универсальный фундамент и альтернативную структуру на основе классов, которая может оказаться более естественной для некоторых решений, чем неструктурированные циклы. Кроме того, они наглядно демонстрируют, насколько хорошо поддержка ООП в языке Python позволяет отображать реальные структуры, такие как файловые системы. Приемы на основе функции os.walk хорошо подходят для одноразовых сценариев, тогда как лучшая расширяемость, уменьшенная избыточность и сокрытие, свойственные приемам ООП, могут быть основным вкладом в разработку действующих программ, которые могут развиваться в течение долгого времени с учетом наших потребностей.
# 4,
—- Эти потребности действительно изменились с течением вре-
<* мени. Между третьим и четвертым изданиями этой книги из ‘*•- Python 3.X была исключена оригинальная функция os.path.
. ■’ walk, и функция os.walk стала единственным инструментом автоматизированного обхода деревьев в стандартной библиотеке. Это привело к тому, что примеры из предыдущего издания, использовавшие os.path.walk, оказались неработоспособными. Тогда как клиенты, реализованные на основе классов-обходчиков, использующих ту же функцию, не пострадали. Поскольку перевод классов-обходчиков на использование функции os.walk не отразился на их интерфейсе, инструменты, использующие их, сохранили работоспособность без переделки.
Это, пожалуй, один из самых ярких примеров преимуществ инкапсуляции в ООП. Будущее нельзя предсказать с достаточной степенью надежности, тем не менее на практике инструменты, определяемые пользователем, такие как классы- обходчики, обычно обеспечивают более полный контроль над изменениями в инструментах стандартной библиотеки, таких как os.walk. Можете поверить мне на слово — как человек, который обновлял три книги о языке Python на протяжении последних 15 лет, я могу с определенной долей уверенности сказать, что Python будет изменяться постоянно!
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011