【问题标题】:Python class as datastorePython 类作为数据存储
【发布时间】:2012-03-03 22:37:51
【问题描述】:

我正在尝试编写一个类似于某种数据存储的 Python 类。因此,例如,我不想使用字典,而是希望以 class.foo 的形式访问我的数据,并且仍然能够做所有很酷的事情,例如像 for x in dataclass 那样对其进行迭代 em>。

以下是我想出的:

class MyStore(object):
    def __init__(self, data):
        self._data = {}
        for d in data:
            # Just for the sake of example
            self._data[d] = d.upper()

    def __iter__(self):
        return self._data.values().__iter__()

    def __len__(self):
        return len(self._data)

    def __contains__(self, name):
        return name in self._data

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

    def __getattr__(self, name):
        return self._data[name]


store = MyStore(['foo', 'bar', 'spam', 'eggs'])
print "Store items:", [item for item in store]
print "Number of items:", len(store)
print "Get item:", store['foo']
print "Get attribute:", store.foo
print "'foo' is in store:", 'foo' in store

而且,显然它有效。万岁!但是如何正确实现属性的设置呢?添加以下内容会导致__getattr__ 的递归限制:

def __setattr__(self, name, value):
    self._data[name] = value

阅读文档,我应该调用超类(对象)__setattr__ 方法以避免递归,但那样我无法控制我的 self._data 字典。

有人能指出我正确的方向吗?

【问题讨论】:

  • 为什么不直接将迭代内容添加到普通对象,并使用其__dict__ 而不是您的字典?
  • 您可以使用sys.setrecursionlimit() 增加递归限制,顺便说一句。

标签: python attributes setattr


【解决方案1】:

试试这个:

def __setattr__(self, name, value):
    super(MyStore, self).__setattr__(name, value)
    self._data[name] = value

但是,您只需将dict 之类的子类化即可为自己省去很多麻烦:

class MyStore(dict):

    def __init__(self, data):
        for d in data:
            self[d] = d.upper()

    def __getattr__(self, name):
        return self[name]

    def __setattr__(self, name, value):
        self[name] = value

store = MyStore(['foo', 'bar', 'spam', 'eggs'])
print "Store items:", [item for item in store]
print "Number of items:", len(store)
print "Get item:", store['foo']
print "Get attribute:", store.foo
print "'foo' is in store:", 'foo' in store
store.qux = 'QUX'
print "Get qux item:", store['qux']
print "Get qux attribute:", store.qux
print "'qux' is in store:", 'qux' in store

哪个输出...

Store items: ['eggs', 'foo', 'bar', 'spam']
Number of items: 4
Get item: FOO
Get attribute: FOO
'foo' is in store: True
Get qux item: QUX
Get qux attribute: QUX
'qux' is in store: True

【讨论】:

  • 啊哈,子类化 dict 确实节省了我的工作。我只需要从问题中添加__iter__ 方法,因此在迭代类时我得到了值而不是键。谢谢!
  • 当然,尽管您正在创建一个具有键和值的 dict 类结构,但让迭代遍历键并使用已经提供的 @ 可能更有意义987654327@ 方法,如果你想迭代值。 :)
  • 很公平,但是因为一旦创建了类,我总是对值感兴趣,这让我不用打电话给.itervalues()。您的评论使我将返回行更改为return self.itervalues(),但看起来更好。
猜你喜欢
  • 2011-04-17
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
  • 1970-01-01
  • 2017-10-28
  • 1970-01-01
  • 2013-09-08
  • 2016-08-16
相关资源
最近更新 更多