我发现它更方便访问字典键作为obj。foo而不是obj['foo'],所以我写了这个片段:
class AttributeDict(dict):
def __getattr__(self, attr):
return self[attr]
def __setattr__(self, attr, value):
self[attr] = value
然而,我认为一定有一些原因,Python没有提供开箱即用的功能。以这种方式访问字典键的注意事项和缺陷是什么?
这不是一个“好”的答案,但我认为这是俏皮的(它不处理嵌套字典在当前形式)。简单地将dict包装在函数中:
def make_funcdict(d=None, **kwargs)
def funcdict(d=None, **kwargs):
if d is not None:
funcdict.__dict__.update(d)
funcdict.__dict__.update(kwargs)
return funcdict.__dict__
funcdict(d, **kwargs)
return funcdict
现在你的语法略有不同。访问dict项就像访问属性f.key一样。要以通常的方式访问dict项(和其他dict方法),请执行f()['key'],我们可以通过使用关键字参数和/或字典调用f来方便地更新dict
例子
d = {'name':'Henry', 'age':31}
d = make_funcdict(d)
>>> for key in d():
... print key
...
age
name
>>> print d.name
... Henry
>>> print d.age
... 31
>>> d({'Height':'5-11'}, Job='Carpenter')
... {'age': 31, 'name': 'Henry', 'Job': 'Carpenter', 'Height': '5-11'}
就是这样。如果有人提出这种方法的优点和缺点,我会很高兴。
为了给答案增加一些变化,sci-kit learn将其实现为一串:
class Bunch(dict):
""" Scikit Learn's container object
Dictionary-like object that exposes its keys as attributes.
>>> b = Bunch(a=1, b=2)
>>> b['b']
2
>>> b.b
2
>>> b.c = 6
>>> b['c']
6
"""
def __init__(self, **kwargs):
super(Bunch, self).__init__(kwargs)
def __setattr__(self, key, value):
self[key] = value
def __dir__(self):
return self.keys()
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(key)
def __setstate__(self, state):
pass
您所需要的是获取setattr和getattr方法—getattr检查字典键,然后继续检查实际属性。setstaet是针对pickle /unpickling“bunch”的修复-如果感兴趣,请检查https://github.com/scikit-learn/scikit-learn/issues/6196
你可以从标准库中获取一个方便的容器类:
from argparse import Namespace
避免复制代码位。没有标准的字典访问,但如果你真的想要的话,很容易得到一个。argparse中的代码很简单,
class Namespace(_AttributeHolder):
"""Simple object for storing attributes.
Implements equality by attribute names and values, and provides a simple
string representation.
"""
def __init__(self, **kwargs):
for name in kwargs:
setattr(self, name, kwargs[name])
__hash__ = None
def __eq__(self, other):
return vars(self) == vars(other)
def __ne__(self, other):
return not (self == other)
def __contains__(self, key):
return key in self.__dict__