我如何使Python字典成员访问通过点“。”?
例如,我想写mydict.val而不是mydict['val']。
我还想以这种方式访问嵌套字典。例如
mydict.mydict2.val
会提到
mydict = { 'mydict2': { 'val': ... } }
我如何使Python字典成员访问通过点“。”?
例如,我想写mydict.val而不是mydict['val']。
我还想以这种方式访问嵌套字典。例如
mydict.mydict2.val
会提到
mydict = { 'mydict2': { 'val': ... } }
当前回答
基于epool的答案,这个版本允许你通过点操作符访问任何字典:
foo = {
"bar" : {
"baz" : [ {"boo" : "hoo"} , {"baba" : "loo"} ]
}
}
例如,foo.bar.baz[1]。爸爸回答“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]
其他回答
使用namedtuple允许点访问。
它就像一个轻量级对象,也具有元组的属性。
它允许定义属性并使用点操作符访问它们。
from collections import namedtuple
Data = namedtuple('Data', ['key1', 'key2'])
dataObj = Data(val1, key2=val2) # can instantiate using keyword arguments and positional arguments
使用点运算符访问
dataObj.key1 # Gives val1
datObj.key2 # Gives val2
使用元组索引进行访问
dataObj[0] # Gives val1
dataObj[1] # Gives val2
但记住这是一个元组;不是字典。因此下面的代码将给出错误
dataObj['key1'] # Gives TypeError: tuple indices must be integers or slices, not str
参考:namedtuple
使用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'])
派生自dict和并实现__getattr__和__setattr__。
或者你也可以用Bunch,非常相似。
我不认为这是可能的monkeypatch内置字典类。
您可以使用SimpleNamespace来实现这一点
from types import SimpleNamespace
# Assign values
args = SimpleNamespace()
args.username = 'admin'
# Retrive values
print(args.username) # output: admin
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