【问题标题】:Instantiated objects in recursive python function seems to keep / get references to other instances递归python函数中的实例化对象似乎保留/获取对其他实例的引用
【发布时间】:2021-02-20 18:18:14
【问题描述】:

使用 python 3.9,我想将一个目录及其子目录映射到一个结构如下的文件夹类:

class Folder:
    path = ''
    sub_folders = list()

    def __init__(self, path):
        self.path = path

我使用以下代码填充主文件夹,然后使用递归填充子文件夹及其子文件夹:

def get_folder(path):
    folder = Folder(path)
    sub_directories = [f.path for f in os.scandir(path) if f.is_dir()]
    for sub_directory in sub_directories:
        folder.sub_folders.append(get_folder(sub_directory))

    return folder

这种方法的结果是每个Folder都有相同的sub_folders列表 Image of the infinite sub_folders

我用 C# 重新创建了代码(我更习惯使用它),它按预期工作。

我觉得文件夹对象的引用被保存并传递给其他对象的方式有些奇怪。

用于参考按预期工作的 C# 代码:

public class Folder
{
    public List<Folder> SubFolders { get; set; } = new List<Folder>();
    public string Path { get; set; }
}

public static Folder GetFolder(string path)
{
    var folder = new Folder();
    folder.Path = path;
    var subFolders = Directory.GetDirectories(path);

    foreach (var subFolder in subFolders)
    {
        folder.SubFolders.Add(GetFolder(subFolder));
    }

    return folder;
}

Image of result from C# code

编辑:

显然我创建了一个类级变量而不是实例级变量。这解决了我的错误:

EDIT2:

移除了类级变量

class Folder:
    def __init__(self, path):
        self.path = path
        self.sub_folders = list()

【问题讨论】:

  • 正在研究它——因为我认为这是一个有趣的问题。最初的想法:在 init 之前你有 path 和 sub_folders 成员。当不附加到 self(C++ 中的“this”)时,它们充当“静态”数据成员,并由同一类的所有实例共享。在 __init__() 构造函数中 self._thing = thing 是你应该做的,所以每个实例都有一个唯一的数据类实例。
  • 只是你创建了一个类级别而不是实例级别的变量sub_folders。因此,一点也不奇怪它会在每个实例之间共享......这完全是类级别变量的目的。
  • @donkopotamus 我明白了,我不知道我实际上创建了一个类级变量。谢谢!我现在修好了。
  • @drw89 ... 在您的“固定”版本中去掉类级别的pathsub_folders ...它们根本不应该存在
  • @donkopotamus 好的,谢谢你的信息。看来我还有很多东西要学!

标签: python recursion instantiation


【解决方案1】:

我认为这可以改进为让 Folder.dirs 返回一个文件夹对象列表...

您的主要逻辑显然是正确的,只是类语法。 我几乎从不使用

class():
   member = ... # <-- 'static' variable - not sure what python calls this.

   def __init__(self):
   """ """

事物的类型。即使在单例模式中,我也发现这有问题。 这种用法我已经好几次了。

我提出的解决方案:

import os

class Folder:
    def __init__(self, path):
        self._path_name = path
        self._dir_names = [f.path for f in os.scandir(path) if f.is_dir()]

    def __str__(self):
        string = 'path: {}'.format(self.path)
        string += '\n'
        string += 'dirs: {}'.format(self.dirs)
        return string

    @property
    def path(self):
        return self._path_name

    @property
    def dirs(self):
        return self._dir_names


def main():
    """ Test the Folder class """
    folder = Folder('.')
    print(folder)

    for sub_folder in folder.dirs:
        folder = Folder(sub_folder)
        print(folder)


if __name__ == "__main__":
    main()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多