我发现它更方便访问字典键作为obj。foo而不是obj['foo'],所以我写了这个片段:
class AttributeDict(dict):
def __getattr__(self, attr):
return self[attr]
def __setattr__(self, attr, value):
self[attr] = value
然而,我认为一定有一些原因,Python没有提供开箱即用的功能。以这种方式访问字典键的注意事项和缺陷是什么?
由于以下原因,我对现有的选项不满意,于是我开发了MetaDict。它的行为完全类似于dict,但支持点表示法和IDE自动补全,而没有其他解决方案的缺点和潜在的名称空间冲突。所有功能和使用示例都可以在GitHub上找到(见上面的链接)。
完全披露:我是MetaDict的作者。
我在尝试其他解决方案时遇到的缺点/限制:
Addict
No key autocompletion in IDE
Nested key assignment cannot be turned off
Newly assigned dict objects are not converted to support attribute-style key access
Shadows inbuilt type Dict
Prodict
No key autocompletion in IDE without defining a static schema (similar to dataclass)
No recursive conversion of dict objects when embedded in list or other inbuilt iterables
AttrDict
No key autocompletion in IDE
Converts list objects to tuple behind the scenes
Munch
Inbuilt methods like items(), update(), etc. can be overwritten with obj.items = [1, 2, 3]
No recursive conversion of dict objects when embedded in list or other inbuilt iterables
EasyDict
Only strings are valid keys, but dict accepts all hashable objects as keys
Inbuilt methods like items(), update(), etc. can be overwritten with obj.items = [1, 2, 3]
Inbuilt methods don't behave as expected: obj.pop('unknown_key', None) raises an AttributeError
这不是一个“好”的答案,但我认为这是俏皮的(它不处理嵌套字典在当前形式)。简单地将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'}
就是这样。如果有人提出这种方法的优点和缺点,我会很高兴。