将具有相同名称的对象传递给字典是修改旧对象(通过引用传递)

Passing objects with same name to dictionary is modifying old objects (pass by reference)

我正在构建一个文件系统分析器,我有一个名为 HashableHeap 的 class,它会覆盖 __hash__ 函数以使用文件扩展名进行哈希处理。我有一本将扩展映射到堆的字典。例如 .jpg 堆需要保存 jpg 对象,当我对 .jpg 进行哈希处理时,它应该给我相应的堆。

问题是:当我遇到不在字典键中的扩展时,我创建了一个新堆并添加了它。当代码尝试创建和添加新堆时,它也会修改第一个堆。例如:假设它首先向 dict 添加一个 .json 堆。然后它遇到一个 .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调试截图:

您需要了解 class 变量和实例变量之间的区别。 Class 变量在 __init__ 函数之外创建,并在 class 的所有实例之间共享。这很少是你想要的。实例变量在 __init__ 函数中创建。它们对于 class.

的每个实例都是唯一的

您正在 __init__ 方法之外创建变量 heap,因此它由 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

class 与实例变量之间存在一些微妙之处。当您分配给一个变量时,例如您的代码行 self.extension = extension,实际上会创建一个实例变量来隐藏同名的 class 变量。如果你想彻底理解这个概念,你需要阅读这篇文章。

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