首页 > 解决方案 > 将同名对象传递给字典正在修改旧对象(通过引用传递)

问题描述

我正在构建一个文件系统分析器,并且我有一个名为 的类HashableHeap,它覆盖了__hash__使用文件扩展名散列的函数。我有一本将扩展映射到堆的字典。例如 .jpg 堆需要保存 jpg 对象,当我为 .jpg 散列时,它应该给我相应的堆。

问题是:当我遇到不在字典键中的扩展时,我会创建一个新堆并添加它。当代码尝试创建和添加一个新堆时,它也会修改第一个堆。例如:假设它首先将 .json 堆添加到 dict。然后它遇到一个 .sql 文件并创建一个同名的新堆。当它添加新堆时,.sql 文件也会添加到 .json 堆中。所有堆都是具有不同键的相同内容。

我认为这是关于引用,我试图删除新的堆对象,但它没有改变。也许我需要像行为一样按值传递,但我是 Python 的初学者。

def add_to_dictionary(directory, abs_path):
    # Creates a file obj from path and adds to heap
    for file in directory:
        try:
            f = File(os.path.join(abs_path, file))
            if f.extension in extension_dictionary.keys():  # check if the corresponding heap exists for extension x
                hashable_heap = extension_dictionary[f.extension]
                hashable_heap.total_size += f.size
                heapq.heappush(hashable_heap.heap, f)
            elif f.extension != '':  # if the heap does not exist, create and add with current file
                new_heap = HashableHeap(f.extension)
                new_heap.total_size = f.size
                extension_dictionary[f.extension] = new_heap
                heapq.heappush(extension_dictionary[f.extension].heap, f)
        except FileNotFoundError:
            print(os.path.join(abs_path, file))
            print('No permission')

这是HashableHeap因为它被请求的代码:

class HashableHeap:
    # wrapper class for heaps, required for the extension based hashing
    heap = []
    extension = ''
    total_size = 0

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

    def __hash__(self):
        hash(self.extension)

    def __lt__(self, other):  # Comparator of the heaps by their sizes
        return self.total_size > other.total_size

PyCharm 调试截图:

PyCharm 调试截图

标签: pythonpython-3.xoperating-systemparameter-passingpass-by-reference

解决方案


您需要了解类变量和实例变量之间的区别。类变量在__init__函数外部创建,并在类的所有实例之间共享。这很少是你想要的。实例变量在__init__函数内部创建。它们对于类的每个实例都是唯一的。

您正在方法heap之外创建变量__init__,因此它由 HashableHeap 的所有实例共享。这正是您所看到的行为。

尝试这个:

class HashableHeap:
    # wrapper class for heaps, required for the extension based hashing
    def __init__(self, extension):
        self.heap = []
        self.total_size = 0
        self.extension = extension
 # Everything else is the same

关于类与实例变量有一些微妙之处。当您分配给变量时,例如您的代码行self.extension = extension,它实际上创建了一个实例变量,该变量隐藏了同名的类变量。如果你想彻底理解这个概念,你需要阅读这个。

顺便说一句,您的 HashableHeap 函数实际上并没有做任何有用的事情。Python 字典已经自动在其键上使用散列算法。当您将键:值对插入字典时,键会为您散列。


推荐阅读