提问人:bodacydo 提问时间:3/1/2010 最后编辑:dreftymacbodacydo 更新时间:9/20/2023 访问量:307675
如何使用点“.”来访问字典的成员?
How to use a dot "." to access members of dictionary?
问:
如何使 Python 字典成员可通过点“.”访问?
例如,与其写,不如写。mydict['val']
mydict.val
我也想以这种方式访问嵌套字典。例如
mydict.mydict2.val
将参考
mydict = { 'mydict2': { 'val': ... } }
答:
派生自 dict 和 和 implement 和 。__getattr__
__setattr__
或者你可以使用非常相似的 Bunch。
我认为不可能 monkeypatch 内置 dict 类。
评论
不要。属性访问和索引在 Python 中是分开的,您不应该希望它们执行相同的操作。创建一个类(可能是由 ),如果你有一些东西应该具有可访问的属性,并使用符号从字典中获取一个项目。namedtuple
[]
评论
语言本身不支持这一点,但有时这仍然是一个有用的要求。除了 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
这将支持这样的事情:
>> test_dict = {'thing': {'spam': 12, 'foo': {'cheeze': 'bar'}}}
>> output = get_var(test_dict, 'thing.spam.foo.cheeze')
>> print output
'bar'
>>
评论
None
{}
dict.get()
return current_data or None
我试过了这个:
class dotdict(dict):
def __getattr__(self, name):
return self[name]
你也可以试试。__getattribute__
让每个字典都成为一种 dotdict 就足够了,如果你想从多层字典中初始化它,也尝试实现。__init__
评论
def docdict(name):
class dotdict(dict): def __getattr__(self, name): if name not in self: return None elif type(self[name]) is dict: return JsonDot(self[name]) else: return self[name]
在库格尔的回答的基础上,考虑到迈克·格雷厄姆(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
我一直把它放在一个 util 文件中。您也可以将其用作您自己的课程的混音。
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'
评论
d = {'foo': {'bar': 'baz'}}; d = dotdict(d); d.foo.bar
d.foo
python class DotDict(dict): """dot.notation access to dictionary attributes""" def __getattr__(*args): val = dict.get(*args) return DotDict(val) if type(val) is dict else val __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__
get
None
安装方式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
与 Bunch 的比较
完全披露:我是 DotMap 的创建者。我创建它是因为缺少这些功能Bunch
- 记住添加项的顺序并按该顺序进行迭代
- 自动创建子项,当您有很多层次结构时,可以节省时间并使代码更简洁
DotMap
- 构造 从 a 并以递归方式将所有子实例转换为
dict
dict
DotMap
评论
{"test.foo": "bar"}
mymap.test.foo
DotMap
**kwargs
c = {**a, **b}
m = DotMap(); m.a = 2; m.b = 3; print('{a} {b}'.format(**m));
2 3
dict()
DotMap()
我最终尝试了 AttrDict 和 Bunch 库,发现它们对我的使用来说很慢。在我和一位朋友研究之后,我们发现编写这些库的主要方法导致库通过嵌套对象积极递归,并在整个过程中复制字典对象。考虑到这一点,我们进行了两个关键的更改。1)我们使属性延迟加载 2)我们不是创建字典对象的副本,而是创建轻量级代理对象的副本。这是最终实现。使用此代码的性能提升令人难以置信。使用 AttrDict 或 Bunch 时,仅这两个库就分别消耗了我请求时间的 1/2 和 1/3(什么!?此代码将该时间减少到几乎为零(在 0.5 毫秒的范围内)。这当然取决于您的需求,但是如果您在代码中经常使用此功能,请务必使用这样简单的东西。
class DictProxy(object):
def __init__(self, obj):
self.obj = obj
def __getitem__(self, key):
return wrap(self.obj[key])
def __getattr__(self, key):
try:
return wrap(getattr(self.obj, key))
except AttributeError:
try:
return self[key]
except KeyError:
raise AttributeError(key)
# you probably also want to proxy important list properties along like
# items(), iteritems() and __len__
class ListProxy(object):
def __init__(self, obj):
self.obj = obj
def __getitem__(self, key):
return wrap(self.obj[key])
# you probably also want to proxy important list properties along like
# __iter__ and __len__
def wrap(value):
if isinstance(value, dict):
return DictProxy(value)
if isinstance(value, (tuple, list)):
return ListProxy(value)
return value
请参阅此处的原始实现,https://stackoverflow.com/users/704327/michael-merickel。
另一件需要注意的事情是,这个实现非常简单,并没有实现你可能需要的所有方法。您需要根据需要在 DictProxy 或 ListProxy 对象上编写这些内容。
你可以用我刚刚做的这个类来做。使用此类,您可以像使用其他字典(包括 json 序列化)或点表示法一样使用该对象。希望能帮到你:Map
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']
评论
.iteritems()
.items()
AttributeError
None
self.update(*args,**kwargs)
__missing__(self,key): value=self[key]= type(self)(); return value
__getstate__
__setstate__
hasattr(Map, 'anystring') is true. which means the hasattr would always return True due to overriding
此解决方案是对 epool 提供的解决方案的改进,旨在满足 OP 以一致的方式访问嵌套字典的要求。epool 的解决方案不允许访问嵌套的字典。
class YAMLobj(dict):
def __init__(self, args):
super(YAMLobj, self).__init__(args)
if isinstance(args, dict):
for k, v in args.iteritems():
if not isinstance(v, dict):
self[k] = v
else:
self.__setattr__(k, YAMLobj(v))
def __getattr__(self, attr):
return self.get(attr)
def __setattr__(self, key, value):
self.__setitem__(key, value)
def __setitem__(self, key, value):
super(YAMLobj, self).__setitem__(key, value)
self.__dict__.update({key: value})
def __delattr__(self, item):
self.__delitem__(item)
def __delitem__(self, key):
super(YAMLobj, self).__delitem__(key)
del self.__dict__[key]
有了这个类,现在可以做这样的事情:.A.B.C.D
评论
def dict_to_object(dick):
# http://stackoverflow.com/a/1305663/968442
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
return Struct(**dick)
如果有人决定将其永久转换为对象,这应该可以。您可以在访问之前创建一个一次性对象。dict
d = dict_to_object(d)
评论
如果你想腌制修改后的字典,你需要在上面的答案中添加一些状态方法:
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
评论
__getattr__ = dict.get
PicklingError: Can't pickle <class '__main__.dot_dict'>: attribute lookup dot_dict on __main__ failed
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__
”。现在你知道怎么做了!
评论
dotdict
dict
不是对OP问题的直接回答,而是受到某些人的启发,也许对某些人有用。我使用内部(绝不是优化的代码)创建了一个基于对象的解决方案__dict__
payload = {
"name": "John",
"location": {
"lat": 53.12312312,
"long": 43.21345112
},
"numbers": [
{
"role": "home",
"number": "070-12345678"
},
{
"role": "office",
"number": "070-12345679"
}
]
}
class Map(object):
"""
Dot style access to object members, access raw values
with an underscore e.g.
class Foo(Map):
def foo(self):
return self.get('foo') + 'bar'
obj = Foo(**{'foo': 'foo'})
obj.foo => 'foobar'
obj._foo => 'foo'
"""
def __init__(self, *args, **kwargs):
for arg in args:
if isinstance(arg, dict):
for k, v in arg.iteritems():
self.__dict__[k] = v
self.__dict__['_' + k] = v
if kwargs:
for k, v in kwargs.iteritems():
self.__dict__[k] = v
self.__dict__['_' + k] = v
def __getattribute__(self, attr):
if hasattr(self, 'get_' + attr):
return object.__getattribute__(self, 'get_' + attr)()
else:
return object.__getattribute__(self, attr)
def get(self, key):
try:
return self.__dict__.get('get_' + key)()
except (AttributeError, TypeError):
return self.__dict__.get(key)
def __repr__(self):
return u"<{name} object>".format(
name=self.__class__.__name__
)
class Number(Map):
def get_role(self):
return self.get('role')
def get_number(self):
return self.get('number')
class Location(Map):
def get_latitude(self):
return self.get('lat') + 1
def get_longitude(self):
return self.get('long') + 1
class Item(Map):
def get_name(self):
return self.get('name') + " Doe"
def get_location(self):
return Location(**self.get('location'))
def get_numbers(self):
return [Number(**n) for n in self.get('numbers')]
# Tests
obj = Item({'foo': 'bar'}, **payload)
assert type(obj) == Item
assert obj._name == "John"
assert obj.name == "John Doe"
assert type(obj.location) == Location
assert obj.location._lat == 53.12312312
assert obj.location._long == 43.21345112
assert obj.location.latitude == 54.12312312
assert obj.location.longitude == 44.21345112
for n in obj.numbers:
assert type(n) == Number
if n.role == 'home':
assert n.number == "070-12345678"
if n.role == 'office':
assert n.number == "070-12345679"
为了建立在 epool 的答案之上,这个版本允许你通过点运算符访问里面的任何字典:
foo = {
"bar" : {
"baz" : [ {"boo" : "hoo"} , {"baba" : "loo"} ]
}
}
例如,返回 .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]
评论
iteritems()
items()
xrange()
range()
我喜欢 Munch,它在点访问之上提供了很多方便的选项。
进口蒙克
temp_1 = {'person': { 'fname': 'senthil', 'lname': 'ramalingam'}}
dict_munch = munch.munchify(temp_1)
dict_munch.person.fname
获得点访问(但不是数组访问)的一种简单方法是在 Python 中使用普通对象。喜欢这个:
class YourObject:
def __init__(self, *args, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
...并像这样使用它:
>>> obj = YourObject(key="value")
>>> print(obj.key)
"value"
...要将其转换为字典,请执行以下操作:
>>> print(obj.__dict__)
{"key": "value"}
使用,非常简单,适用于
Python 3.4.3 中文文档__getattr__
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
这也适用于嵌套字典,并确保稍后附加的字典的行为相同:
class DotDict(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Recursively turn nested dicts into DotDicts
for key, value in self.items():
if type(value) is dict:
self[key] = DotDict(value)
def __setitem__(self, key, item):
if type(item) is dict:
item = DotDict(item)
super().__setitem__(key, item)
__setattr__ = __setitem__
__getattr__ = dict.__getitem__
我最近遇到了“Box”库,它做同样的事情。
安装命令:pip install python-box
例:
from box import Box
mydict = {"key1":{"v1":0.375,
"v2":0.625},
"key2":0.125,
}
mydict = Box(mydict)
print(mydict.key1.v1)
我发现它比 dotmap 等其他现有库更有效,当您有大型嵌套字典时,它会生成 python 递归错误。
图书馆和详细信息的链接: https://pypi.org/project/python-box/
@derek73的答案很整洁,但不能腌制,也不能(深)抄,而且会因为缺少钥匙而返回。下面的代码解决了这个问题。None
编辑:我没有看到上面的答案解决了完全相同的问题(赞成)。我把答案留在这里供参考。
class dotdict(dict):
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def __getattr__(self, name):
try:
return self[name]
except KeyError:
raise AttributeError(name)
评论
__getattr__ = dict.__getitem__
用: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'])
评论
PyCharm
与常规类不同,代码完成不适用于 SimpleNamespace。这对我来说是一个交易破坏者 stackoverflow.com/q/71348706/3753826
使用允许点访问。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
我只需要使用虚线路径字符串访问字典,所以我想出了:
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
这是一个古老的问题,但我最近发现它有一个可通过键访问的实现版本,即 https://scikit-learn.org/stable/modules/generated/sklearn.utils.Bunch.html#sklearn.utils.Bunchsklearn
dict
Bunch
您可以使用 SimpleNamespace 实现此目的
from types import SimpleNamespace
# Assign values
args = SimpleNamespace()
args.username = 'admin'
# Retrive values
print(args.username) # output: admin
评论
SimpleNamespace
dict
json.dumps
用于无限级别的字典、列表、字典列表和列表的字典嵌套。
它还支持酸洗
这是这个答案的延伸。
class DotDict(dict):
# https://stackoverflow.com/a/70665030/913098
"""
Example:
m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
Iterable are assumed to have a constructor taking list as input.
"""
def __init__(self, *args, **kwargs):
super(DotDict, self).__init__(*args, **kwargs)
args_with_kwargs = []
for arg in args:
args_with_kwargs.append(arg)
args_with_kwargs.append(kwargs)
args = args_with_kwargs
for arg in args:
if isinstance(arg, dict):
for k, v in arg.items():
self[k] = v
if isinstance(v, dict):
self[k] = DotDict(v)
elif isinstance(v, str) or isinstance(v, bytes):
self[k] = v
elif isinstance(v, Iterable):
klass = type(v)
map_value: List[Any] = []
for e in v:
map_e = DotDict(e) if isinstance(e, dict) else e
map_value.append(map_e)
self[k] = klass(map_value)
def __getattr__(self, attr):
return self.get(attr)
def __setattr__(self, key, value):
self.__setitem__(key, value)
def __setitem__(self, key, value):
super(DotDict, self).__setitem__(key, value)
self.__dict__.update({key: value})
def __delattr__(self, item):
self.__delitem__(item)
def __delitem__(self, key):
super(DotDict, self).__delitem__(key)
del self.__dict__[key]
def __getstate__(self):
return self.__dict__
def __setstate__(self, d):
self.__dict__.update(d)
if __name__ == "__main__":
import pickle
def test_map():
d = {
"a": 1,
"b": {
"c": "d",
"e": 2,
"f": None
},
"g": [],
"h": [1, "i"],
"j": [1, "k", {}],
"l":
[
1,
"m",
{
"n": [3],
"o": "p",
"q": {
"r": "s",
"t": ["u", 5, {"v": "w"}, ],
"x": ("z", 1)
}
}
],
}
map_d = DotDict(d)
w = map_d.l[2].q.t[2].v
assert w == "w"
pickled = pickle.dumps(map_d)
unpickled = pickle.loads(pickled)
assert unpickled == map_d
kwargs_check = DotDict(a=1, b=[dict(c=2, d="3"), 5])
assert kwargs_check.b[0].d == "3"
kwargs_and_args_check = DotDict(d, a=1, b=[dict(c=2, d="3"), 5])
assert kwargs_and_args_check.l[2].q.t[2].v == "w"
assert kwargs_and_args_check.b[0].d == "3"
test_map()
评论
_pickle.PicklingError: Can't pickle <class '__main__.DotDict'>: attribute lookup DotDict on __main__ failed
最简单的解决方案。
定义一个只包含 pass 语句的类。为此类创建对象并使用点表示法。
class my_dict:
pass
person = my_dict()
person.id = 1 # create using dot notation
person.phone = 9999
del person.phone # Remove a property using dot notation
name_data = my_dict()
name_data.first_name = 'Arnold'
name_data.last_name = 'Schwarzenegger'
person.name = name_data
person.name.first_name # dot notation access for nested properties - gives Arnold
评论
dict()
pprint.pprint(person)
__repr__
dict()
我不喜欢在(超过)10 年的火灾中添加另一个日志,但我也会查看我最近发布的 dotwiz
库 - 实际上就在今年。
这是一个相对较小的库,在基准测试中获取(访问)和设置(创建)时间方面也表现得非常好,至少与其他替代方案相比是这样。
安装方式dotwiz
pip
pip install dotwiz
它做你想做的一切和子类,所以它像一个普通的字典一样运行:dict
from dotwiz import DotWiz
dw = DotWiz()
dw.hello = 'world'
dw.hello
dw.hello += '!'
# dw.hello and dw['hello'] now both return 'world!'
dw.val = 5
dw.val2 = 'Sam'
最重要的是,您可以将其转换为对象或从对象转换:dict
d = dw.to_dict()
dw = DotWiz(d) # automatic conversion in constructor
这意味着,如果您要访问的内容已经形成,您可以将其转换为便于访问:dict
DotWiz
import json
json_dict = json.loads(text)
data = DotWiz(json_dict)
print data.location.city
最后,我正在做的一件令人兴奋的事情是现有的功能请求,以便它自动创建新的子实例,以便您可以执行如下操作:DotWiz
dw = DotWiz()
dw['people.steve.age'] = 31
dw
# ✫(people=✫(steve=✫(age=31)))
与dotmap
我在下面添加了与 dotmap
的快速和肮脏的性能比较。
首先,使用以下命令安装这两个库:pip
pip install dotwiz dotmap
出于基准测试目的,我想出了以下代码:
from timeit import timeit
from dotwiz import DotWiz
from dotmap import DotMap
d = {'hey': {'so': [{'this': {'is': {'pretty': {'cool': True}}}}]}}
dw = DotWiz(d)
# ✫(hey=✫(so=[✫(this=✫(is=✫(pretty={'cool'})))]))
dm = DotMap(d)
# DotMap(hey=DotMap(so=[DotMap(this=DotMap(is=DotMap(pretty={'cool'})))]))
assert dw.hey.so[0].this['is'].pretty.cool == dm.hey.so[0].this['is'].pretty.cool
n = 100_000
print('dotwiz (create): ', round(timeit('DotWiz(d)', number=n, globals=globals()), 3))
print('dotmap (create): ', round(timeit('DotMap(d)', number=n, globals=globals()), 3))
print('dotwiz (get): ', round(timeit("dw.hey.so[0].this['is'].pretty.cool", number=n, globals=globals()), 3))
print('dotmap (get): ', round(timeit("dm.hey.so[0].this['is'].pretty.cool", number=n, globals=globals()), 3))
结果,在我的 M1 Mac 上运行 Python 3.10:
dotwiz (create): 0.189
dotmap (create): 1.085
dotwiz (get): 0.014
dotmap (get): 0.335
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
这对于在 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
评论
dotwiz
上一个:如何查询嵌套对象?
下一个:C 语言中的嵌套函数
评论
d[a][b][c]
d[a, b, c]
{"my.key":"value"}