我如何使Python字典成员访问通过点“。”?
例如,我想写mydict.val而不是mydict['val']。
我还想以这种方式访问嵌套字典。例如
mydict.mydict2.val
会提到
mydict = { 'mydict2': { 'val': ... } }
我如何使Python字典成员访问通过点“。”?
例如,我想写mydict.val而不是mydict['val']。
我还想以这种方式访问嵌套字典。例如
mydict.mydict2.val
会提到
mydict = { 'mydict2': { 'val': ... } }
当前回答
我只需要使用虚线路径字符串访问字典,所以我想到了:
def get_value_from_path(dictionary, parts):
""" extracts a value from a dictionary using a dotted path string """
if type(parts) is str:
parts = parts.split('.')
if len(parts) > 1:
return get_value_from_path(dictionary[parts[0]], parts[1:])
return dictionary[parts[0]]
a = {'a':{'b':'c'}}
print(get_value_from_path(a, 'a.b')) # c
其他回答
派生自dict和并实现__getattr__和__setattr__。
或者你也可以用Bunch,非常相似。
我不认为这是可能的monkeypatch内置字典类。
如果你已经在使用pandas,你可以构造一个pandas Series或DataFrame,从中你可以通过点语法访问项目:
1级字典:
import pandas as pd
my_dictionary = pd.Series({
'key1': 'value1',
'key2': 'value2'
})
print(my_dictionary.key1)
# Output: value1
2级字典:
import pandas as pd
my_dictionary = pd.DataFrame({
'key1': {
'inner_key1': 'value1'
},
'key2': {
'inner_key2': 'value2'
}
})
print(my_dictionary.key1.inner_key1)
# Output: value1
请注意,这可能在规范化数据结构(其中每个字典条目都具有相同的结构)下工作得更好。在上面的第二个例子中,得到的DataFrame是:
key1 key2
inner_key1 value1 NaN
inner_key2 NaN value2
@derek73的答案非常简洁,但它不能被pickle或(深度)复制,并且它在缺少键时返回None。下面的代码修复了这个问题。
编辑:我没有看到上面的答案解决了完全相同的问题(点赞)。我把答案留在这里供参考。
class dotdict(dict):
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def __getattr__(self, name):
try:
return self[name]
except KeyError:
raise AttributeError(name)
Fabric有一个非常好的、最小的实现。将其扩展为允许嵌套访问,我们可以使用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
这详细阐述了Kugel的回答“从dict和派生并实现__getattr__和__setattr__”。现在你知道怎么做了!
kaggle_environments使用的实现是一个名为structify的函数。
class Struct(dict):
def __init__(self, **entries):
entries = {k: v for k, v in entries.items() if k != "items"}
dict.__init__(self, entries)
self.__dict__.update(entries)
def __setattr__(self, attr, value):
self.__dict__[attr] = value
self[attr] = value
# Added benefit of cloning lists and dicts.
def structify(o):
if isinstance(o, list):
return [structify(o[i]) for i in range(len(o))]
elif isinstance(o, dict):
return Struct(**{k: structify(v) for k, v in o.items()})
return o
https://github.com/Kaggle/kaggle-environments/blob/master/kaggle_environments/utils.py
这可能有助于在《ConnectX》等游戏中测试AI模拟代理
from kaggle_environments import structify
obs = structify({ 'remainingOverageTime': 60, 'step': 0, 'mark': 1, 'board': [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]})
conf = structify({ 'timeout': 2, 'actTimeout': 2, 'agentTimeout': 60, 'episodeSteps': 1000, 'runTimeout': 1200, 'columns': 7, 'rows': 6, 'inarow': 4, '__raw_path__': '/kaggle_simulations/agent/main.py' })
def agent(obs, conf):
action = obs.step % conf.columns
return action