2

我正在使用 Python 3。shelve在文档中宣传为dict. 但是,在我的使用中,事实证明shelve不允许元组作为键,而 dict 允许:

import shelve
def tryShelve():
    db = shelve.open("shelvefile")
    db["word1"] = 1
    db[("word1", "word2")] = 15

tryShelve()

产生此错误:

Traceback (most recent call last):
  File "<pyshell#41>", line 1, in <module>
    tryShelve()
  File "<pyshell#40>", line 4, in tryShelve
    db[("word1", "word2")] = 15
  File "C:\Python32\lib\shelve.py", line 125, in __setitem__
    self.dict[key.encode(self.keyencoding)] = f.getvalue()
AttributeError: 'tuple' object has no attribute 'encode'
4

4 回答 4

4

模块文档shelve第一段:

“架子”是一个持久的、类似字典的对象。与“dbm”数据库的区别在于架子中的值(不是键!)本质上可以是任意的 Python 对象——pickle 模块可以处理的任何东西。这包括大多数类实例、递归数据类型和包含大量共享子对象的对象。键是普通字符串。

[强调我的]

yaml模块允许元组作为键:

>>> d = {}
>>> d["word1"] = 1
>>> d[("word1", "word2")] = 15
>>> import yaml
>>> yaml.dump(d)
'word1: 1\n? !!python/tuple [word1, word2]\n: 15\n'
>>> yaml.load(_)
{('word1', 'word2'): 15, 'word1': 1}
于 2011-03-20T09:11:47.837 回答
2

元组在 Python 2.7.1 版本中都不能用作键shelve。2.7.1文档建议查看 ActiveState Persistent 字典配方。我对其进行了测试,它似乎可以使用元组作为键,如您的示例代码中所示的'csv'格式,虽然不是'jason'格式(我没有尝试'pickle')。如果你看一下食谱,你就会明白我所说的“格式”是什么意思。

于 2011-03-20T09:20:51.073 回答
1

在我看来,搁置无法序列化元组以写入文件。
考虑pickle作为替代方案。

于 2011-03-20T09:11:24.013 回答
1

在将元组用作搁置中的键之前,您可以使用dumpsand将它们转换为字符串。loads或者,如果您的元组仅包含文字,您可以使用repr(your_tuple)来获取一个字符串表示,您可以使用literal_eval.

为了使转换更方便,您可以继承Shelf和覆盖__getitem____setitem__在访问时自动进行转换。

于 2011-03-20T09:14:56.433 回答