简体   繁体   English

用于存储键值对的Python中的类与字典

[英]Classes vs Dictionaries in Python for storing key-value pairs

I need to define some key-value parameters to configure the behaviour of a class. 我需要定义一些键值参数来配置类的行为。 My requirements are two: 我的要求是两个:

  • To be able to process them programatically 能够以编程方式处理它们
  • To be able to make more specific configurations that overwrite some of the values. 能够进行覆盖某些值的更具体的配置。

The natural approach for the first requirement is to use a dict (so I can loop over keys, values or items with a for loop), but for the second requirement it seems more appropriate to use a class hierarchy and let the attribute lookup mechanism to do the work (plus I get other goodies like being able to use properties for some values). 对于第一个要求的自然的方法是使用dict (这样我就可以遍历键,值或物品用for循环),但对于第二个要求似乎更适合使用类层次结构,让属性查找机制做的工作(加上我得到的其他好东西,比如能够使用某些值的属性)。

Is there a way to get best of both worlds? 有没有办法让两全其美?


After reading the comments, It does not need to be mutable (I won't be changing the values of an already created instance), it's just for static configuration. 阅读完评论后,它不需要是可变的(我不会改变已经创建的实例的值),它只是用于静态配置。 But I might need to add new values in a more specific instance. 但我可能需要在更具体的实例中添加新值。

I think in the end I could just use a dict.copy + dict.update for the specific instances (I can live without the properties). 我想最后我可以使用dict.copy + dict.update来表示特定的实例(我可以没有属性)。

Somehow along the lines of what suggested in the commment by Fabio, I would remark that the two are not mutually exclusive, given that in Python [nearly] everything is an object (including classes!). 不知何故,就像Fabio在文章中提出的那样,我会注意到两者并不相互排斥,因为在Python中[几乎]所有东西都是一个对象(包括类!)。

One obvious solution is - again quoting Fabio - subclassing a dict . 一个明显的解决方案是 - 再次引用法比奥 - 继承一个dict The other would be make your own class starting from the collections.abc containers (using an abstract base class ( abc ) is not a requirement, but would probably the most pythonic way to implement your own container from scratch). 另一个是从collections.abc容器开始创建自己的类(使用抽象基类abc )不是必需的,但可能是从头开始实现自己的容器的最pythonic方式)。

HTH! HTH!

If you can use python 3.3 ChainMap is exactly what you want. 如果你可以使用python 3.3 ChainMap正是你想要的。

http://docs.python.org/3.3/library/collections#collections.ChainMap http://docs.python.org/3.3/library/collections#collections.ChainMap

It's basically a list of dictionaries and will look for a given key in each one sequentially until a match is found. 它基本上是一个字典列表,并将按顺序查找每个字典中的给定键,直到找到匹配项。

Actually, here's the code to use it in 2.7: 实际上,这是在2.7中使用它的代码:

http://code.activestate.com/recipes/305268-chained-map-lookups/ http://code.activestate.com/recipes/305268-chained-map-lookups/

is this what you need? 这就是你需要的吗?

class my_dict(dict):
    def __getattr__(self, name):
        return self[name]
    def __setattr__(self, name, value):
        self[name] = value

d = my_dict()
d.key = "value"
print d.key       #>>>value

for k,v in d.items():
    print k,v     #>>>key value

You could just use named tuples . 你可以使用命名元组 See here and the accepted answer on this question for a nice introduction to them. 请参阅此处以及此问题的已接受答案,以便对其进行详细介绍。 Some important points from that answer are: 该答案的一些重点是:

  • They were added in Python 2.6 and Python 3.0, although there is a recipe for implementation in Python 2.4. 它们是在Python 2.6和Python 3.0中添加的,尽管在Python 2.4中有一个实现的配方

  • Named tuples are backwards compatible with normal tuples 命名元组向后兼容正常元组

Also, named tuples have a number of useful methods such as _fields to get the names of the used and an _asdict method which returns an (ordered) dict of the named tuple contents. 此外,命名元组有许多有用的方法,例如_fields来获取_fields的名称和_asdict方法,它返回命名元组内容的(有序) dict

Here's my take: 这是我的看法:

class Config(object):
    def _keys(self):
        return (name for name in dir(self) if not name.startswith('_'))
    __iter__ = _keys

    def _values(self):
        return (getattr(self, name) for name in self)

    def _items(self):
        return ((name, getattr(self, name)) for name in self)

>>> class Foo(Config):
...     bar = 3
...     baz = 'spam'
...
>>> class Sub(Foo):
...     bar = 4
...
>>> x = Sub()
>>> list(x._items())
[('bar', 4), ('baz', 'spam')]
>>>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM