python - 将同名对象传递给字典正在修改旧对象(通过引用传递)
问题描述
我正在构建一个文件系统分析器,并且我有一个名为 的类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 调试截图:
解决方案
您需要了解类变量和实例变量之间的区别。类变量在__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 字典已经自动在其键上使用散列算法。当您将键:值对插入字典时,键会为您散列。
推荐阅读
- azure - 拉取请求完成时 AzureDev Ops YAML 管道触发
- firebase - 获取文档数据颤动的错误映射
- javascript - 使用 Vue 3 填充 HTML 表格
- c# - c# (ado) alter table add column - 为变量中的列命名 (Datetime)
- azure - Azure VM - 操作无法完成,因为它导致超出批准的标准 Dv2Family 核心配额
- datatables - jQuery Datatables 添加 2 列
- java - 在kafka流应用程序中关闭或不关闭RocksDB Cache和WriteBufferManager
- c# - 获取属性的属性
- docker - 无法使用 wurstmeister/kafka docker 构建多代理 kafka
- python - Python - 列出要求