在python set 2中如何可能有相同的元素?是python的错误吗?你知道吗
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
为什么它适用于dictionary而不适用于set?我以为这是哈希表中的冲突,但事实上重复的对象是同一个对象,所以在添加下一个元素时,在集合查找中找不到它(?)你知道吗
其他信息:
Chunk
定义了__hash__
和__eq__
方法Chunk
有一些属性会抛出一个错误-这不重要,因为它们没有被调用data_chunks = data_chunks | another_set
编辑
区块实现
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)
生成存储库中chunks对象的唯一哈希:chunks和相应的文件映射。稍后它将调用压缩作业,然后设置compressedMd5和现有块的其他属性。
generation_strategy = Strategy.CachingGenerationStrategy(
result_handler,
Settings().extra_io_threads,
)
data_chunks = Strategy.DepotChunker(repository, chunking_strategy, generation_strategy)()
在DeputChunker init上:todo分块作业是基于分块策略设置准备的。然后generation_strategy.__call__
方法处理所有作业:根据先前定义的块对象将文件分割成小块。这是在multiprocessing.Pool
中完成的。创建物理块之后,检查md5,并用compressedMd5
、compressedSize
和product_id
更新块对象。
然后(仅在更改Chunk object后)将Chunk对象添加到set。
这个集合是从DepotChunker
返回的
然后压缩的块被保存在缓存中。你知道吗
然后,所有的数据块都搜索小尺寸的小对象,从中创建由合并的小文件组成的物理块(内存缓冲区中)。我们把它们叫做小块。它们被添加到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)
此时,从一开始就记录了调试器会话
一个问题是
__eq__
对于一个有compressedMd5
而另一个没有compressedMd5
的对象对是不可交换的(即其compressedMd5
被设置为None
)。这意味着可以构造两个对象a
和b
,使得a == b
同时b != a
。你知道吗一个相关的问题是
__eq__
和__hash__
在相似的情况下不一致(__eq__
会拒绝看other.compressedMd5
如果self.compressedMd5
是None
)易变性也可能是一个问题,如下例所示:
在我的电脑上,这会产生
set([<__main__.Chunk object at 0x106d03390>, <__main__.Chunk object at 0x106d03390>])
,即同一对象在集合中出现两次。你知道吗如果更改
md5
或设置/取消设置/更改compressedMd5
,代码中可能会发生类似的情况。你知道吗好吧,我知道这是一种很难可靠重现的行为,所以我们所能提供的只是关于可能导致此类问题的建议。。。你知道吗
除了NPE已经提到的,你确实有一个潜在的问题
Chunk
是可变的:md5
和compressedMd5
属性可以随时更改,因此hash(chunk)
的结果不能保证是稳定的。您可能需要在这里检查您的代码库,以查找最终的小精灵。如果在achunk
被添加到集合之后发现任何更新这些属性之一的代码,那么可能就是罪魁祸首。FWIW请记住,Python从不隐式地复制这样的内容:会反映出
chunks
的变化,把一切都搞砸(注:是的,你很可能已经知道了,但对于来自更主流语言的人来说,这是一个非常常见的陷阱)注意:这只是一个问题,如果任何东西改变了其中一个属性,当然,但使它们成为只读的仍然会更安全(好吧,至少根据Python对“只读”和“安全”即xD的定义)。你知道吗
相关问题 更多 >
编程相关推荐