Почему моя рекурсивная функция не возвращает все данные?

У меня есть функция Python для возврата всех файлов в некотором каталоге (и его подкаталогах) в виде массива numpy, она просматривает все файлы (как показано оператором печати), но возвращает только те, которые указаны в пути к файлу. уточнил, что происходит? Вот моя минимальная воспроизводимая версия:

import os
import numpy as np

def read_path(path, items):
    for item in os.listdir(path):
        if "." in item:
            items = np.append(items, f"{path}\{item}")
            print(f"File: {item}")
        else:
            read_path(f"{path}\{item}", items)
            print(f"Folder: {item}")
    return items

f = np.array([])
print(
    read_path(r"D:\Reubens stuff\Code Stuff\code saves\Python\Create Texture Pack\samples-load\resource_pack\textures", f)
)

Опечатка? Блок else никогда не модифицирует items. (То есть возвращаемое значение read_path игнорируется в блоке else.)

David 24.07.2024 17:26

Этот вопрос похож на: Почему моя рекурсивная функция возвращает None?. Если вы считаете, что это другое, отредактируйте вопрос, поясните, чем он отличается и/или как ответы на этот вопрос не помогают решить вашу проблему.

David 24.07.2024 17:34

Вам следует посмотреть pathlib.Path.rglob и не изобретать велосипед, например, files = np.array([file for file in pathlib.Path('<your_path>').rglob('*') if file.is_file()])

Mark Tolonen 24.07.2024 19:03
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
76
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Как отметил Дэвид, вам нужно добавить возвращаемое значение рекурсии к исходному массиву items. Следовательно, следующий код должен работать:

import os
import numpy as np

def read_path(path, items):
    for item in os.listdir(path):
        full_path = os.path.join(directory_path, item)
        if os.path.isfile(full_path):
            items = np.append(items, f"{path}\{item}")
            print(f"File: {item}")
        else:
            items = np.append(items, read_path(f"{path}\{item}", items))
            print(f"Folder: {item}")
    return items

f = np.array([])
print(
    read_path(r"D:\Reubens stuff\Code Stuff\code saves\Python\Create Texture Pack\samples-load\resource_pack\textures", f)
)

Рекурсия основана на объединении возвращаемых результатов. Но ваш оператор возврата бесполезен. Лучше использовать либо глобальную переменную f, либо классическую рекурсию:

import os

def read_path(path):
    items=[]
    for item in os.listdir(path):
        if "." in item:
            items.append(f"{path}/{item}")
            print(f"File: {item}")
        else:
            items.append(read_path(f"{path}/{item}"))
            print(f"Folder: {item}")
    return items

print(
    read_path(r"D:\Reubens stuff\Code Stuff\code saves\Python\Create Texture Pack\samples-load\resource_pack\textures"")
)

Я также предлагаю определить, является ли элемент файлом или каталогом по этому условию:

os.path.isdir(os.path.join(path, item))

Основная причина вашей проблемы в том, что numpy.append не похож на list.append. Он не изменяет массив (или список) на месте. Скорее, он возвращает массив, содержащий копию данных во входном контейнере (плюс добавляемый элемент). Это означает, что после первой рекурсии вы работаете с другим объектом items, отличным от того, который был изначально передан.

Если вы хотите, чтобы новое значение было передано обратно, вам нужно сделать items = read_path(f"{path}\{item}", items) в блоке else, чтобы items обновлялось в каждом случае.

Другие вопросы по теме