Библиотека, которая используется для построения деревьев, рассчитана только на неизменяемые файловые структуры. То есть уже после создания ее поменять нельзя. Но можно на основе старой структуры сделать новую, в которой какие-то части будут изменены.
Неизменяемая структура выбрана для этого курса не случайно. Такую структуру легче отлаживать и меньше шансов допустить ошибки. И она позволяет максимально погрузиться в использование функций высшего порядка.
Пакет 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(fs.get_name, 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(fs.get_name, 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'}
Вам ответят команда поддержки Хекслета или другие студенты.
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
Наши выпускники работают в компаниях:
С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.
Зарегистрируйтесь или войдите в свой аккаунт