Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Манипуляции с виртуальной файловой системой Python: Деревья

Библиотека, которая используется для построения деревьев, рассчитана только на неизменяемые файловые структуры. То есть уже после создания её поменять нельзя. Но можно на основе старой структуры сделать новую, в которой какие-то части будут изменены.

Неизменяемая структура выбрана для этого курса не случайно. Такую структуру легче отлаживать и меньше шансов допустить ошибки. И она позволяет максимально погрузиться в использование функций высшего порядка.

Базовые операции с узлами

Пакет python-immutable-fs-trees позволяет не только создавать, но и извлекать данные из уже созданных файлов и директорий. Они позволяют не лезть во внутреннюю структуру самого дерева:

from hexlet import fs
tree = fs.mkdir('/', [fs.mkfile('hexlet.log')], {'hidden': True})
fs.get_name(tree)
# '/'
fs.get_meta(tree).get('hidden')
# True
[file] = fs.get_children(tree)
fs.get_name(file)
# 'hexlet.log'
fs.get_meta(file).get('unknown')

# А вот так делать не надо
# У файлов нет детей
fs.get_children(file)

Дополнительно в пакете есть две функции для проверки типа. С их помощью можно выборочно работать с файлами и директориями:

from hexlet import fs
tree = fs.mkdir('/', [fs.mkfile('hexlet.log')], {'hidden': True})
fs.is_directory(tree)
# True
fs.is_file(tree)
# False
[file] = fs.get_children(tree)
fs.is_file(file)
# True
fs.is_directory(file)
# False

Рассмотренных операций хватит для выполнения любых преобразований над файлами и директориями. Начнём с самых простых, которые не требуют рекурсивного обхода.

Обработка

Любая обработка в неизменяемом стиле сводится к формированию новых данных на основе старых. Ниже мы реализуем некоторые варианты преобразования, раскрывающие эту идею.

Изменение имени файла

from hexlet import fs
import copy

file = fs.mkfile('one', {'size': 35})
# При переименовании важно сохранить метаданные
new_meta = copy.deepcopy(fs.get_meta(file))
new_file = fs.mkfile('new name', new_meta)

Фактически здесь создаётся новый файл с метаданными старого. Перед тем как создать новый файл, метаданные клонируются (глубоким клонированием). Почему? Словари передаются по ссылке, и если не выполнить клонирование, то в метаданных нового файла окажутся метаданные старого. Как только мы захотим изменить что-то, то изменив новое — сломаем старое:

file = fs.mkfile('one', {'size': 35})
new_meta = fs.get_meta(file)
new_meta['size'] = 15
new_file = fs.mkfile('new name', new_meta)
fs.get_meta(new_file)
# {'size': 15}

# Бум! У file тоже поменялись метаданные
fs.get_meta(file)
# {'size': 15}

Сортировка содержимого директории

tree = fs.mkdir('/', [
    fs.mkfile('one'),
    fs.mkfile('two'),
    fs.mkdir('three'),
])

children = fs.get_children(tree)
new_meta = copy.deepcopy(fs.get_meta(tree))
# reverse изменяет массив, поэтому клонируем
new_children = children[:]
# Сортировка в обратном порядке (разворачиваем список)
new_children.reverse()
tree2 = fs.mkdir(fs.get_name(tree), new_children, new_meta)
list(map(lambda node: fs.get_name(node), fs.get_children(tree2)))
# ['three', 'two', 'one']

Обновление содержимого директории

tree = fs.mkdir('/', [
    fs.mkfile('oNe'),
    fs.mkfile('Two'),
    fs.mkdir('THREE'),
])

# Приведение к нижнему регистру имён директорий и файлов внутри конкретной директории
def to_lower(node):
    name = fs.get_name(node)
    new_meta = copy.deepcopy(fs.get_meta(node))
    if fs.is_directory(node):
        return fs.mkdir(name.lower(), fs.get_children(node), new_meta)
    return fs.mkfile(name.lower(), new_meta)

children = fs.get_children(tree)
new_children = list(map(to_lower, children))
# Обязательно копируем метаданные
new_meta = copy.deepcopy(fs.get_meta(tree))
tree2 = fs.mkdir(fs.get_name(tree), new_children, new_meta)
list(map(lambda node: fs.get_name(node), fs.get_children(tree2)))
# ['one', 'two', 'three']

Удаление файлов внутри директории

tree = fs.mkdir('/', [
    fs.mkfile('one'),
    fs.mkfile('two'),
    fs.mkdir('three'),
])

children = fs.get_children(tree)
new_children = list(filter(fs.is_directory, children))
new_meta = copy.deepcopy(fs.get_meta(tree))
fs.mkdir(fs.get_name(tree), new_children, new_meta)
# {'name': '/', 'children': [{'name': 'three', 'children': [], 'meta': {}, 'type': 'directory'}], 'meta': {}, 'type': 'directory'}

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
900
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 130 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Python-разработчик
Профессия
Разработка веб-приложений на Django
25 мая 10 месяцев

Используйте Хекслет по максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»