С рекурсией – вызовом функцией самой себя мы уже дело имели, считая факториал. Рассмотрим ещё один пример, который без рекурсии реализовать практически невозможно. Выведем на экран структуру папок на диске.
Алгоритм простой – начиная от заданного пути, найдём все папки и повторим это действие для каждой из найденных папок. Для поиска папок и файлов будем использовать функцию scandir() из пакета os. Итак, для начала импортируем этот модуль в приложение:
import os
Для рекурсии нам потребуется определить функцию, которая будет вызывать сама себя. Назовём её getdirlist – получение списка папок. Её код простой:
def getdirlist(path):
dirs = os.scandir(path)
for dir in dirs:
if not dir.name.startswith('.') and dir.is_dir():
print(indent + dir.name)
getdirlist(path + dir.name + '\\',)
Эта функция будет работать и делать то, что надо, но попробуем её улучшить.
Первое. Все папки будут выводиться по одной на строку, при этом их структура будет не видна. Можно либо выводить полный путь, либо добавить отступ, например, в два пробела. Сделаем второе. Отступ будем передавать как второй аргумент, чтобы при необходимости можно было изменить. По умолчанию сделаем его пустой строкой:
def getdirlist(path, indent = ''):
dirs = os.scandir(path)
for dir in dirs:
if not dir.name.startswith('.') and dir.is_dir():
print(indent + dir.name)
getdirlist(path + dir.name + '\\', indent + ' ')
Двойной обратный слэш – не ошибка. Он имеет особое назначение – «экранирует» спецсимволы, позволяя их обрабатывать как обычные. И для того, чтобы он обрабатывался как обычный символ, печатаем его дважды.
Второе. Не забываем про права доступа к файлам и папкам в операционной системе. Здесь мы делаем для Windows, но права доступа есть и в Linux, и в macOS. И при отсутствии доступа к папке работа приложения аварийно завершится. Значит, эту ситуацию надо обрабатывать. Используем блок try – except – else – finally. Последняя часть нам не нужна – у нас не будет кода, который должен выполняться и при наличии ошибок, и при отсутствии. Поэтому функция будет выглядеть так:
def getdirlist(path, indent = ''):
try:
dirs = os.scandir(path)
except:
pass
else:
for dir in dirs:
if not dir.name.startswith('.') and dir.is_dir():
print(indent + dir.name)
getdirlist(path + dir.name + '\\', indent + ' ')
Добавляем импорт модуля и вызов функции и получаем полный код приложения:
import os
def getdirlist(path, indent = ''):
try:
dirs = os.scandir(path)
except:
pass
else:
for dir in dirs:
if not dir.name.startswith('.') and dir.is_dir():
print(indent + dir.name)
getdirlist(path + dir.name + '\\', indent + ' ')
getdirlist('С:\\Users\\')
Не пробуйте запустить это приложение, указав в качестве начального пути корень диска C: или / для Linux или macOS. Результат будете ждать достаточно долго.