ссылка на репл если окно ниже не работает
На предыдущем уроке мы написали функцию, которая «прогуливается» по указанной директории и выводит на экран наименования всех файлов, которые она нашла. Давайте немного модифицируем нашу функцию.
Во-первых, переименуем её в find_big_file(dir)
. Изменения должны коснуться трёх строк.
Во-вторых, вместо того чтобы переписывать переменную name, объявим отдельную переменную abs_name, которая будет хранить абсолютный путь.
Во-третьих, давайте рядом с именем будем выводить размер файла. В этом нам поможет функция getsize()
из модуля path библиотеки os.
Не всегда результат может быть ожидаемым
А дальше дело за малым. Нужно просто сравнить все значения и найти наибольшее. Объявим переменную max_size=0 и name_big_file= ‘ ‘ . Будем обновлять значения переменных, если нашёлся файл больший чем текущий. И в конце после выхода из цикла, просто выведем информацию на экран.
Но код работает на так, как мы ожидали. Мало того что он не ищет большой файл, он ещё и выводит вместо одной строчки несколько. Почему? Мы ведь использовали функцию print()
за пределам цикла, после его окончания работы. Всё дело в рекурсии! print()
действительно находится за пределами цикла, но сколько раз функция find_big_file()
вызывает саму себя, столько раз мы увидим строчку с именем и размером файла. Более того, переменные max_size и name_big_file обнуляются при каждом вызове функции, поэтому мы получаем такой хаос. Рекомендую набрать код данной функции и, прежде чем продолжить, попробовать решить эту проблему.
True story
А что если при каждом вызове функции показатели размера самого большого файла и его имени, не сбрасывались бы, а сохранялись и передавались между функциями. Таким образом, на каком бы уровне рекурсии мы сейчас не находились, у нас всегда бы была актуальная информация о том, какой файл сейчас самый большой.
В данной ситуации нас спасёт ссылочная модель хранения данных. При передаче параметров в функцию, некоторые из них передаются по значению, а некоторые по ссылке. Это зависит от типа данных передаваемых в аргументе. У чисел и строк предаётся значение (иными словами копия данных), а у списков и словарей передаётся ссылка (иными словами указатель на область оперативной памяти где хранится список или словарь).
Из-за ссылочной передачи значения, если мы поменяем такой объект внутри функции, то он у нас изменится и за её пределами. Вот такие вот фокусы! Не переживайте, если вы не совсем понимаете как работает передача параметра по значению или по ссылке, это очень большая и отдельная тема. Главное что стоит подчеркнуть — если мы передаём ссылочный аргумент, то мы работаем не с копией, а с оригиналом.
Пишем код.
Перед вызовом функции объявим словарь big_file, который хранит информацию о имени и размере самого большого файла. Именно этот словарь будет изменяться внутри функции find_big_file()
. Передадим его вторым параметром. А после мы просто распечатаем big_file.
Далее, объявим ещё один параметр file_info, в нём будет храниться наш словарь. Изменим условие где мы сравниваем размер текущего файла с размером большого файла. И внутри условия будем обращаться по ключам к нашему словарю и менять их значения, если нашёлся файл большего размера, чем указан в словаре.
А на этом всё! Можно переходить к подведению итогов.