【问题标题】:Is it normal to use an object as its own key in a dictionary/hashmap (in python)?在字典/哈希映射(在python中)中使用对象作为自己的键是否正常?
【发布时间】:2017-06-07 13:08:04
【问题描述】:

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

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)

【问题讨论】:

  • 如果thing 是不可变的(它必须是,否则你不能将它用作键),也许set() 是一个更好的缓存容器?
  • 断章取意,使用 Object 的某些属性作为键 item.some_unique_id(可能是其他属性的元组/组合)会更好吗?

标签: python dictionary hashmap hashtable


【解决方案1】:

很遗憾,是的。其实有点想多了。您需要做的就是使用sets

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

您的代码可以替换为

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 problem。为什么不发布一个新问题并解释您要解决的问题。

【讨论】:

  • 如果我有多个 item_records 怎么办?每当我收到一大块新的输入数据时,就会有一个新的一天。我仍然想要一个缓存,但我不能为记录使用相同的结构。
  • 我不明白你的评论
  • 嗯,好的,但我认为最好在这里澄清评论。
  • 抱歉。让我澄清一下。仅使用一组的问题是我对传入项目的顺序或数量一无所知。假设我连续两次收到一件物品...我希望将其反映在记录中。
  • @Ferguzz 您只需要item_record 中的订单和号码,对吗?不在item_cache?所以使用item_cache 的集合并继续使用item_record 的列表。
猜你喜欢
  • 2013-06-30
  • 2020-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-21
  • 1970-01-01
  • 2012-02-18
  • 2019-09-15
相关资源
最近更新 更多