在字典/hashmap(在python中)中使用对象作为自己的键是正常的吗



假设我有一个正在处理的传入项目流。对于每个项目,我提取一些数据并存储。但很多项目都是相同的。我想跟踪收到它们的情况,但不要多次存储相同的数据。我可以这样实现它,但它看起来很笨重:

item_cache = {}
item_record = []
def process(input_item):
item = Item(input_item)  # implements __hash__
try:
item_record.append(item_cache[item])
except KeyError:
item_cache[item] = item  # this is the part that seems weird
item_record.append(item)

我只是想多了?在python中执行d[thing] = thing是一个相当正常的构造吗?

编辑

作为对以下评论的回应。下面是一个更完整的示例,展示了此代码如何避免存储输入数据的重复副本。

class Item(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def __eq__(self, other):
return self.a == other.a and self.b == other.b and self.c == other.c
def __ne__(self, other):
return not (self == other)
def __hash__(self):
return hash((self.a, self.b, self.c))
def __repr__(self):
return '(%s, %s, %s)' % (self.a, self.b, self.c)

item_cache = {}
item_record = []

def process_item(new_item):
item = Item(*new_item)
try:
item_record.append(item_cache[item])
except KeyError:
item_cache[item] = item
item_record.append(item)
del item  # this happens anyway, just adding for clarity.
for item in ((1, 2, 3), (2, 3, 4), (1, 2, 3), (2, 3, 4)):
process_item(item)
print([id(item) for item in item_record])
print(item_record)

很遗憾是的。事实上,这是一种过度思考。你所需要做的就是使用集合

集合对象是不同可散列对象的无序集合。常见用途包括成员身份测试、从序列和计算数学运算,并集、差分和对称差分。

您的代码可以替换为

item_record = set()
for .... :
item_record.add(input_item)

更新尽管您说"但不能多次存储相同的数据",但您的代码实际上确实多次存储该项。在原始代码中,无论项缓存中是否存在项,都将执行item_record.append()调用

try:
item_record.append(item_cache[item])
except KeyError:
item_cache[item] = item  # this is the part that seems weird
item_record.append(item)

因此,该列表将有重复项。但是,我不太确定您是否添加了正确的对象,因为您还没有共享Item类的代码。我相信我们真正遇到的是xy问题。为什么不发布一个新问题并解释你想要解决的问题呢。

最新更新