bod*_*ydo 230 python syntax dictionary nested
如何通过点"."访问Python字典成员?
例如,mydict['val']
我不想写作,而是写作mydict.val
.
此外,我想以这种方式访问嵌套的dicts.例如
mydict.mydict2.val
Run Code Online (Sandbox Code Playgroud)
会参考
mydict = { 'mydict2': { 'val': ... } }
Run Code Online (Sandbox Code Playgroud)
der*_*k73 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'
Run Code Online (Sandbox Code Playgroud)
epo*_*ool 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]
Run Code Online (Sandbox Code Playgroud)
用法示例:
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']
Run Code Online (Sandbox Code Playgroud)
Chr*_*ord 100
dotmap
通过安装pip
pip install dotmap
Run Code Online (Sandbox Code Playgroud)
它完成了你想要它做的一切和子类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'
Run Code Online (Sandbox Code Playgroud)
最重要的是,您可以将它转换为dict
对象:
d = m.toDict()
m = DotMap(d) # automatic conversion in constructor
Run Code Online (Sandbox Code Playgroud)
这意味着如果您要访问的内容已经在dict
表单中,您可以将其转换DotMap
为便于访问:
import json
jsonDict = json.loads(text)
data = DotMap(jsonDict)
print data.location.city
Run Code Online (Sandbox Code Playgroud)
最后,它会自动创建新的子DotMap
实例,以便您可以执行以下操作:
m = DotMap()
m.people.steve.age = 31
Run Code Online (Sandbox Code Playgroud)
完全披露:我是DotMap的创建者.我创建它因为Bunch
缺少这些功能
DotMap
创建,当您拥有大量层次结构时,可以节省时间并使代码更清晰dict
并递归地将所有子dict
实例转换为DotMap
Dmi*_*kov 27
使用SimpleNamespace
:
>>> from types import SimpleNamespace
>>> d = dict(x=[1, 2], y=['a', 'b'])
>>> ns = SimpleNamespace(**d)
>>> ns.x
[1, 2]
>>> ns
namespace(x=[1, 2], y=['a', 'b'])
Run Code Online (Sandbox Code Playgroud)
tdi*_*ihp 18
我试过这个:
class dotdict(dict):
def __getattr__(self, name):
return self[name]
Run Code Online (Sandbox Code Playgroud)
你也可以试试__getattribute__
.
使每个dict成为一种dotdict就足够了,如果你想从多层dict中初始化它,也可以尝试实现__init__
.
Dav*_*ave 17
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
Run Code Online (Sandbox Code Playgroud)
按如下方式使用它:
keys = AttributeDict()
keys.abc.xyz.x = 123
keys.abc.xyz.a.b.c = 234
Run Code Online (Sandbox Code Playgroud)
这详细阐述了库格尔的"从字典中__getattr__
__setattr__
得出并实施和"的回答.现在你知道了!
Pra*_*pta 15
I recently came across the 'Box' library which does the same thing.
Installation command : pip install python-box
Example:
from box import Box
mydict = {"key1":{"v1":0.375,
"v2":0.625},
"key2":0.125,
}
mydict = Box(mydict)
print(mydict.key1.v1)
Run Code Online (Sandbox Code Playgroud)
I found it to be more effective than other existing libraries like dotmap, which generate python recursion error when you have large nested dicts.
link to library and details: https://pypi.org/project/python-box/
小智 15
您可以使用 SimpleNamespace 来实现这一点
from types import SimpleNamespace
# Assign values
args = SimpleNamespace()
args.username = 'admin'
# Retrive values
print(args.username) # output: admin
Run Code Online (Sandbox Code Playgroud)
别.属性访问和索引是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
Run Code Online (Sandbox Code Playgroud)
语言本身不支持这一点,但有时这仍然是一个有用的要求。除了 Bunch 配方之外,您还可以编写一个小方法,可以使用点字符串访问字典:
def get_var(input_dict, accessor_string):
"""Gets data from a dictionary using a dotted accessor-string"""
current_data = input_dict
for chunk in accessor_string.split('.'):
current_data = current_data.get(chunk, {})
return current_data
Run Code Online (Sandbox Code Playgroud)
这将支持这样的事情:
>> test_dict = {'thing': {'spam': 12, 'foo': {'cheeze': 'bar'}}}
>> output = get_var(test_dict, 'thing.spam.foo.cheeze')
>> print output
'bar'
>>
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
为了建立在 epool 的回答之上,这个版本允许你通过点运算符访问任何内部的字典:
foo = {
"bar" : {
"baz" : [ {"boo" : "hoo"} , {"baba" : "loo"} ]
}
}
Run Code Online (Sandbox Code Playgroud)
例如,foo.bar.baz[1].baba
返回"loo"
。
class Map(dict):
def __init__(self, *args, **kwargs):
super(Map, self).__init__(*args, **kwargs)
for arg in args:
if isinstance(arg, dict):
for k, v in arg.items():
if isinstance(v, dict):
v = Map(v)
if isinstance(v, list):
self.__convert(v)
self[k] = v
if kwargs:
for k, v in kwargs.items():
if isinstance(v, dict):
v = Map(v)
elif isinstance(v, list):
self.__convert(v)
self[k] = v
def __convert(self, v):
for elem in range(0, len(v)):
if isinstance(v[elem], dict):
v[elem] = Map(v[elem])
elif isinstance(v[elem], list):
self.__convert(v[elem])
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]
Run Code Online (Sandbox Code Playgroud)
我不喜欢在(超过)10 年的火灾中添加另一根木头,但我也会查看dotwiz
我最近发布的库 - 实际上就在今年。
这是一个相对较小的库,在基准测试中的获取(访问)和设置(创建)时间方面也表现得非常好,至少与其他替代方案相比是这样。
\n安装dotwiz
通过pip
pip install dotwiz\n
Run Code Online (Sandbox Code Playgroud)\n它可以完成您想要它做的所有事情并进行子类化dict
,因此它的操作就像普通的字典一样:
from dotwiz import DotWiz\n\ndw = DotWiz()\ndw.hello = \'world\'\ndw.hello\ndw.hello += \'!\'\n# dw.hello and dw[\'hello\'] now both return \'world!\'\ndw.val = 5\ndw.val2 = \'Sam\'\n
Run Code Online (Sandbox Code Playgroud)\n最重要的是,您可以将其与dict
对象相互转换:
d = dw.to_dict()\ndw = DotWiz(d) # automatic conversion in constructor\n
Run Code Online (Sandbox Code Playgroud)\n这意味着,如果您想要访问的内容已经在dict
表单中,您可以将其转换为DotWiz
以便于访问:
import json\njson_dict = json.loads(text)\ndata = DotWiz(json_dict)\nprint data.location.city\n
Run Code Online (Sandbox Code Playgroud)\n最后,我正在处理的一些令人兴奋的事情是现有的功能请求,以便它自动创建新的子DotWiz
实例,以便您可以执行以下操作:
dw = DotWiz()\ndw[\'people.steve.age\'] = 31\n\ndw\n# \xe2\x9c\xab(people=\xe2\x9c\xab(steve=\xe2\x9c\xab(age=31)))\n
Run Code Online (Sandbox Code Playgroud)\ndotmap
我在下面添加了一个快速而肮脏的性能比较dotmap
。
首先,使用以下命令安装两个库pip
:
pip install dotwiz dotmap\n
Run Code Online (Sandbox Code Playgroud)\n我出于基准目的想出了以下代码:
\npip install dotwiz\n
Run Code Online (Sandbox Code Playgroud)\n结果,在我的 M1 Mac 上运行 Python 3.10:
\ndotwiz (create): 0.189\ndotmap (create): 1.085\ndotwiz (get): 0.014\ndotmap (get): 0.335\n
Run Code Online (Sandbox Code Playgroud)\n
使用__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)
Run Code Online (Sandbox Code Playgroud)
输出:
10000
StackOverflow
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
129458 次 |
最近记录: |