【发布时间】:2019-12-01 09:38:52
【问题描述】:
如何在 python set 2 中拥有相同的元素?是python的bug吗?
type(data_chunks)
<class 'set'>
len(data_chunks)
43130
same = [x for x in data_chunks if x.md5==chunk.md5]
[<Model.Chunk.Chunk o...x0DB40870>, <Model.Chunk.Chunk o...x0DB40870>]
len(same)
2
same[0] is same[1]
True
same[0] == same[1]
True
len(set(same))
1
但是当我用它构建字典时,重复被删除了!
len({k:k.product_id for k in data_chunks})
43129
为什么它适用于字典而不适用于集合?我虽然认为这是哈希表中的冲突,但实际上重复的对象是同一个对象,所以在添加下一个元素时在集合查找中找不到它(?)
附加信息:
-
Chunk定义了__hash__和__eq__方法 - python 3.7.2
- 我已经意识到
Chunk有一些会引发错误的属性 - 这应该不重要,因为它们没有被调用 - 执行代码行是:
data_chunks = data_chunks | another_set - 在 vscode 中调试会话期间的交互式提示
- 在运行代码时有时
- 但在这一调试会话期间,从 data_chunks 创建新集的长度始终相同
编辑
块实现
class Chunk(object):
def __init__(self,
md5,
size=None,
compressedMd5=None,
# ... (more elements)
product_id=None):
self.md5 = md5
self.product_id = product_id
# (etc.)
def __eq__(self, other):
if self.compressedMd5:
return self.compressedMd5 == other.compressedMd5 and self.product_id == other.product_id
return self.md5 == other.md5 and self.product_id == other.product_id
def __hash__(self):
return self.name.__hash__()
@property
def name(self):
return self.compressedMd5 if self.compressedMd5 is not None else self.md5
===================
编辑 好的,所以代码中的内容如下:
repository - json 描述符
chunking_strategy = ... - 主要是存储设置的类,例如块将被压缩。
result_handler = Strategy.DefaultResultHandler(repository)
在存储库中生成块对象的唯一哈希:块和相应的文件映射。 稍后它将调用压缩作业,然后设置compressedMd5 和现有块的其他属性。
generation_strategy = Strategy.CachingGenerationStrategy(
result_handler,
Settings().extra_io_threads,
)
data_chunks = Strategy.DepotChunker(repository, chunking_strategy, generation_strategy)()
在 DeputChunker init 上:todo 分块作业是根据 chunking_strategy 设置准备的。然后generation_strategy.__call__ 方法处理所有作业:根据先前定义的 Chunk 对象将文件切成小块。这是在multiprocessing.Pool 中完成的。在创建物理块后,它们会检查 md5,并使用compressedMd5、compressedSize 和 product_id更新 块对象。
然后(只是在更改 Chunk 对象之后)将块对象添加到 set。
这套是从DepotChunker返回的
然后将压缩后的块保存在缓存中。
然后所有 data_chunk 都在搜索具有小尺寸的小对象,从中创建由合并的小文件组成的物理块(在内存缓冲区中)。让我们称它们为 smallFilesChunks。它们被添加到data_chunks:
sfChunk = Chunk(
sfCompressedContentMD5, # yes I see that this is compressed md5 - it was intended for some reason I don't know
size=sfSize,
compressedMd5=sfCompressedContentMD5,
compressedSize=sfCompressedSize,
product_id=productId
)
if not sfChunk in data_chunks: # purly sanity check
data_chunks.add(sfcChunk)
最后元文件被创建,它们也被分块并添加到data_chunks
然后元文件被转储,它们也被分块。
for depot in manifest_depots:
data_chunks = data_chunks | simpleChunker(depot)
此时调试器会话从一开始就被记录了
【问题讨论】:
-
可能还需要查看
Chunk的实现,以确定散列的任何问题 -
是的,我们来看看哈希函数和比较方法。
-
另外,
Chunk是可变的吗? -
@Mesco 请编辑您的帖子以包含适当的最小可重现示例 (stackoverflow.com/help/minimal-reproducible-example)
-
似乎
__hash__在compressedMd5或md5上使用__hash__方法 - 他们是否以相同的方式实现__hash__?您正在构建列表same仅基于md5属性的相等性,而__hash__is 和__eq__也在检查其他属性。
标签: python hash set hashtable hash-collision