如何通过点"."访问Python字典成员?
例如,mydict['val']
我不想写作,而是写作mydict.val
.
此外,我想以这种方式访问嵌套的dicts.例如
mydict.mydict2.val
会参考
mydict = { 'mydict2': { 'val': ... } }
derek73.. 219
我一直把它保存在一个util文件中.您也可以在自己的课程中使用它作为mixin.
class dotdict(dict): """dot.notation access to dictionary attributes""" __getattr__ = dict.get __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__ mydict = {'val':'it works'} nested_dict = {'val':'nested works too'} mydict = dotdict(mydict) mydict.val # 'it works' mydict.nested = dotdict(nested_dict) mydict.nested.val # 'nested works too'
@tmthyjames你可以简单地在getter方法中返回dotdict类型对象以递归方式访问带点符号的属性,如:```python class DotDict(dict):"""dot.notation访问字典属性"""def __getattr __(*args ):val = dict.get(*args)如果type(val)是dict,则返回DotDict(val),否则val __setattr__ = dict .__ setitem__ __delattr__ = dict .__ delitem__``` (13认同)
+1表示简单.但似乎不适用于嵌套的dicts.`d = {'foo':{'bar':'baz'}}; d = dotdict(d); d.foo.bar`抛出一个属性错误,但``d.foo`工作正常. (7认同)
非常简单的答案,太棒了!你碰巧知道我需要做什么才能在IPython工作中完成制表工作吗?该类需要实现__dir __(self),但不知怎的,我无法让它工作. (4认同)
经过实验,`get`的确是个坏主意,因为它会返回`None`而不是因为缺少项目而引发错误... (3认同)
是的,这不适用于复杂的嵌套结构. (2认同)
epool.. 127
你可以使用我刚刚创建的这个类来完成它.使用此类,您可以Map
像使用另一个字典(包括json序列化)或使用点表示法一样使用该对象.我希望能帮助你:
class Map(dict): """ Example: m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer']) """ def __init__(self, *args, **kwargs): super(Map, self).__init__(*args, **kwargs) for arg in args: if isinstance(arg, dict): for k, v in arg.iteritems(): self[k] = v if kwargs: for k, v in kwargs.iteritems(): self[k] = v def __getattr__(self, attr): return self.get(attr) def __setattr__(self, key, value): self.__setitem__(key, value) def __setitem__(self, key, value): super(Map, self).__setitem__(key, value) self.__dict__.update({key: value}) def __delattr__(self, item): self.__delitem__(item) def __delitem__(self, key): super(Map, self).__delitem__(key) del self.__dict__[key]
用法示例:
m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer']) # Add new key m.new_key = 'Hello world!' # Or m['new_key'] = 'Hello world!' print m.new_key print m['new_key'] # Update values m.new_key = 'Yay!' # Or m['new_key'] = 'Yay!' # Delete key del m.new_key # Or del m['new_key']
为了处理Python 3,我将`.iteritems()`更新为`.items()` (16认同)
请注意,这将与普通期望的行为不同,因为如果该属性不存在,它将不会引发"AttributeError".相反,它会返回`None`. (9认同)
您可以将构造函数简化为`self.update(*args,**kwargs)`.另外,你可以添加`__missing __(self,key):value = self [key] = type(self)(); 返回值`.然后,您可以使用点表示法添加缺少的条目.如果你想要它是可选择的,你可以添加`__getstate__`和`__setstate__` (4认同)
Chris Redfor.. 100
dotmap
通过安装pip
pip install dotmap
它完成了你想要它做的一切和子类dict
,所以它像普通的字典一样运行:
from dotmap import DotMap m = DotMap() m.hello = 'world' m.hello m.hello += '!' # m.hello and m['hello'] now both return 'world!' m.val = 5 m.val2 = 'Sam'
最重要的是,您可以将它转换为dict
对象:
d = m.toDict() m = DotMap(d) # automatic conversion in constructor
这意味着如果您要访问的内容已经在dict
表单中,您可以将其转换DotMap
为便于访问:
import json jsonDict = json.loads(text) data = DotMap(jsonDict) print data.location.city
最后,它会自动创建新的子DotMap
实例,以便您可以执行以下操作:
m = DotMap() m.people.steve.age = 31
完全披露:我是DotMap的创建者.我创建它因为Bunch
缺少这些功能
记住订单项是按顺序添加和迭代的
自动子项DotMap
创建,当您拥有大量层次结构时,可以节省时间并使代码更清晰
从a构造dict
并递归地将所有子dict
实例转换为DotMap
Kugel.. 56
从dict派生并实现__getattr__
和__setattr__
.
或者你可以使用非常相似的束.
我不认为monkeypatch内置的dict类是可能的.
我一直把它保存在一个util文件中.您也可以在自己的课程中使用它作为mixin.
class dotdict(dict): """dot.notation access to dictionary attributes""" __getattr__ = dict.get __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__ mydict = {'val':'it works'} nested_dict = {'val':'nested works too'} mydict = dotdict(mydict) mydict.val # 'it works' mydict.nested = dotdict(nested_dict) mydict.nested.val # 'nested works too'
你可以使用我刚刚创建的这个类来完成它.使用此类,您可以Map
像使用另一个字典(包括json序列化)或使用点表示法一样使用该对象.我希望能帮助你:
class Map(dict): """ Example: m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer']) """ def __init__(self, *args, **kwargs): super(Map, self).__init__(*args, **kwargs) for arg in args: if isinstance(arg, dict): for k, v in arg.iteritems(): self[k] = v if kwargs: for k, v in kwargs.iteritems(): self[k] = v def __getattr__(self, attr): return self.get(attr) def __setattr__(self, key, value): self.__setitem__(key, value) def __setitem__(self, key, value): super(Map, self).__setitem__(key, value) self.__dict__.update({key: value}) def __delattr__(self, item): self.__delitem__(item) def __delitem__(self, key): super(Map, self).__delitem__(key) del self.__dict__[key]
用法示例:
m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer']) # Add new key m.new_key = 'Hello world!' # Or m['new_key'] = 'Hello world!' print m.new_key print m['new_key'] # Update values m.new_key = 'Yay!' # Or m['new_key'] = 'Yay!' # Delete key del m.new_key # Or del m['new_key']
dotmap
通过安装pip
pip install dotmap
它完成了你想要它做的一切和子类dict
,所以它像普通的字典一样运行:
from dotmap import DotMap m = DotMap() m.hello = 'world' m.hello m.hello += '!' # m.hello and m['hello'] now both return 'world!' m.val = 5 m.val2 = 'Sam'
最重要的是,您可以将它转换为dict
对象:
d = m.toDict() m = DotMap(d) # automatic conversion in constructor
这意味着如果您要访问的内容已经在dict
表单中,您可以将其转换DotMap
为便于访问:
import json jsonDict = json.loads(text) data = DotMap(jsonDict) print data.location.city
最后,它会自动创建新的子DotMap
实例,以便您可以执行以下操作:
m = DotMap() m.people.steve.age = 31
完全披露:我是DotMap的创建者.我创建它因为Bunch
缺少这些功能
记住订单项是按顺序添加和迭代的
自动子项DotMap
创建,当您拥有大量层次结构时,可以节省时间并使代码更清晰
从a构造dict
并递归地将所有子dict
实例转换为DotMap
从dict派生并实现__getattr__
和__setattr__
.
或者你可以使用非常相似的束.
我不认为monkeypatch内置的dict类是可能的.
我试过这个:
class dotdict(dict): def __getattr__(self, name): return self[name]
你也可以试试__getattribute__
.
使每个dict成为一种dotdict就足够了,如果你想从多层dict中初始化它,也可以尝试实现__init__
.
Fabric有一个非常好的,最小的实现.扩展它以允许嵌套访问,我们可以使用a defaultdict
,结果看起来像这样:
from collections import defaultdict class AttributeDict(defaultdict): def __init__(self): super(AttributeDict, self).__init__(AttributeDict) def __getattr__(self, key): try: return self[key] except KeyError: raise AttributeError(key) def __setattr__(self, key, value): self[key] = value
按如下方式使用它:
keys = AttributeDict() keys.abc.xyz.x = 123 keys.abc.xyz.a.b.c = 234
这详细阐述了库格尔的"从字典中__getattr__
__setattr__
得出并实施和"的回答.现在你知道了!
别.属性访问和索引是Python中的独立事物,您不应该希望它们执行相同的操作.namedtuple
如果你有一些应该具有可访问属性的东西并使用[]
符号从dict中获取一个项目,那么创建一个类(可能由一个类创建).
如果你想修改你修改过的字典,你需要在上面的答案中添加一些状态方法:
class DotDict(dict): """dot.notation access to dictionary attributes""" def __getattr__(self, attr): return self.get(attr) __setattr__= dict.__setitem__ __delattr__= dict.__delitem__ def __getstate__(self): return self def __setstate__(self, state): self.update(state) self.__dict__ = self
在Kugel的回答的基础上,考虑到Mike Graham的谨慎言辞,如果我们制作一个包装器怎么办?
class DictWrap(object):
""" Wrap an existing dict, or create a new one, and access with either dot
notation or key lookup.
The attribute _data is reserved and stores the underlying dictionary.
When using the += operator with create=True, the empty nested dict is
replaced with the operand, effectively creating a default dictionary
of mixed types.
args:
d({}): Existing dict to wrap, an empty dict is created by default
create(True): Create an empty, nested dict instead of raising a KeyError
example:
>>>dw = DictWrap({'pp':3})
>>>dw.a.b += 2
>>>dw.a.b += 2
>>>dw.a['c'] += 'Hello'
>>>dw.a['c'] += ' World'
>>>dw.a.d
>>>print dw._data
{'a': {'c': 'Hello World', 'b': 4, 'd': {}}, 'pp': 3}
"""
def __init__(self, d=None, create=True):
if d is None:
d = {}
supr = super(DictWrap, self)
supr.__setattr__('_data', d)
supr.__setattr__('__create', create)
def __getattr__(self, name):
try:
value = self._data[name]
except KeyError:
if not super(DictWrap, self).__getattribute__('__create'):
raise
value = {}
self._data[name] = value
if hasattr(value, 'items'):
create = super(DictWrap, self).__getattribute__('__create')
return DictWrap(value, create)
return value
def __setattr__(self, name, value):
self._data[name] = value
def __getitem__(self, key):
try:
value = self._data[key]
except KeyError:
if not super(DictWrap, self).__getattribute__('__create'):
raise
value = {}
self._data[key] = value
if hasattr(value, 'items'):
create = super(DictWrap, self).__getattribute__('__create')
return DictWrap(value, create)
return value
def __setitem__(self, key, value):
self._data[key] = value
def __iadd__(self, other):
if self._data:
raise TypeError("A Nested dict will only be replaced if it's empty")
else:
return other
我喜欢Munch,它在点访问的基础上提供了许多方便的选择。
进口午餐
temp_1 = {'person':{'fname':'senthil','lname':'ramalingam'}}
dict_munch = munch.munchify(temp_1)
dict_munch.person.fname
使用__getattr__
非常简单,可在Python 3.4.3中使用
class myDict(dict): def __getattr__(self,val): return self[val] blockBody=myDict() blockBody['item1']=10000 blockBody['item2']="StackOverflow" print(blockBody.item1) print(blockBody.item2)
输出:
10000 StackOverflow