0

我正在实现一个使用字典来存储数据的东西。除了普通数据外,它还存储一些内部数据,所有数据都以_. 但是,我想将图书馆的用户与这些数据隔离开来,因为他通常不关心它。此外,我需要modified在我的班级中设置一个标志来跟踪数据是否被修改。

对于所有的接口函数,这都很好,这里有两个例子,一个有修改,一个没有修改。请注意,在这种情况下,我不会隐藏内部数据,因为它是故意要求作为键的:

def __getitem__(self, key):
    return self._data[key]

def __setitem__(self, key, value):
    self.modified = True
    self._data[key] = value

在某些功能上,例如__iter__,我会在生成数据之前过滤掉所有以开头_的内容。

但是一个函数在这里会产生真正的问题:popitem. 在其正常行为中,它只会撤回任意项目并在从字典中删除它时返回它。但是,问题来了:没有深入的内部知识,我不知道会提前返回哪个项目。但我知道这遵循与andpopitem相同的规则。所以我确实想出了一个实现:itemskeys

keys = self._data.keys()
for k in keys:
    if k.startswith("_"):
        continue
    v = self._data.pop(k)
    self.modified = True
    return k, v
else:
    raise KeyError('popitem(): dictionary is empty')

此实现有效。但它感觉不合常规,一点也不动态或干净。它也确实很难像这样引发异常:{}.popitem()这看起来很疯狂,但至少会给我一种动态的方式(例如,如果异常消息或类型发生变化,我不必调整)。

我现在追求的是一种更干净、更不疯狂的方法来解决这个问题。会有一种从字典中删除内部数据的方法,但我只会把这条路作为最后的手段。那么你有什么食谱或想法吗?

4

3 回答 3

2

给你的对象两个dict 属性:self._dataself._internal_data. 然后将所有 dict 方法转发到self._data,您就不必过滤掉任何东西。

编辑:好的,我最后错过了“最后的手段”。但我怀疑管理两个 dict 比“修复”每个 dict 方法和运算符要容易得多。:)

于 2013-11-04T23:56:22.907 回答
1
  1. 子类dict而不是包装字典。你需要实现的东西要少得多。
  2. 将您的“内部数据”存储为对象的属性,而不是字典。这样,如果您需要它们,它们很容易获得,但不会出现在普通迭代中。如果在某些时候您需要将它们组合起来,请这样做x = dict(self); x.update(self.__dict__)以创建一个具有两组值的新字典。

如果您确实想将内部数据存储为字典,请嵌入该字典。在您的主要对象上实施__missing__,以便您可以从内部字典中获取项目,如果它们在主要对象中找不到。

于 2013-11-05T00:13:53.497 回答
0

好吧,逻辑是正确的,您可以将其简化为:

self._data.pop(next((key for key in self._data if not key.startswith('_')), 'popitem(): dictionary is empty'))

因此,找到self._data不以 开头的下一个键_,否则将其默认为不会匹配字典中任何其他键的键,这样当弹出失败时,您会自动得到KeyError抛出(使用您的“错误信息”)

于 2013-11-05T00:08:27.400 回答