python - 嵌套字典到具有属性的类似对象的字典
问题描述
假设我有两个(简单的玩具)嵌套数据结构,如下所示:
d = dict(zip(list('abc'), list(range(3))))
nested_dict = {k:d.copy() for k in d}
nested_listof_dict = {k:[d.copy() for _ in range(3)] for k in d}
现在我想让它的行为更像一个“常规”类对象(意思是点可索引)
class dictobj(dict):
def __init__(self, data: dict, name):
data['_name'] = name
super().__init__(data)
for name, item in data.items():
if isinstance(item, (list, tuple)):
setattr(self, name, [dictobj(x, name) if isinstance(x, dict) else x for x in item])
else:
setattr(self, name, dictobj(item, name) if isinstance(item, dict) else item)
def __repr__(self):
return f"{self['_name']}"
data_dictobj = dictobj(data, 'test') # size 1185 bytes
它适用于嵌套字典和nested_listof_dict
assert nested_listof_dict.a[0].b == nested_listof_dict['a'][0]['b']
但是,由于属性和字典都是可变的,这可能会发生
nested_listof_dict['a'][0]['b'] = 2
assert nested_listof_dict.a[0].b != nested_listof_dict['a'][0]['b'] # unwanted behavior
因此,将属性实现为属性是一个好主意。我认为由于闭包作用域而避免使用 lambda 函数可能是一个好主意。首先看如何实现 getter,我关注的是 nested_dict,因为它是一个更简单的结构。
class dictobj(dict):
def __init__(self, data: dict, name):
def make_property(self, name, item):
def getter(self):
return dictobj(item, name) if isinstance(item, dict) else item
setattr(self.__class__, name, property(getter))
# def setter(self, value):
# if not isinstance(value, type(item)):
# raise ValueError(f'cannot change the data structure, expected '+
# f'{type(item).__name__} got {type(value).__name__}')
# self[name] = value
# setattr(self.__class__, name, property(getter, setter))
data['_name'] = name
super().__init__(data)
for name, item in data.items():
if isinstance(item, (list, tuple)):
setattr(self, name, [dictobj(x, name) if isinstance(x, dict) else x for x in item])
else:
make_property(self, name, item)
def __repr__(self):
return f"{self['_name']}"
然后测试是否无法再设置该属性
d = dictobj(d, 'test')
# d.a = 1 # fails as should: "AttributeError: can't set attribute"
# d.a.a = 1 # fails as should: "AttributeError: can't set attribute"
但不知何故我仍然搞砸了,观察到以下行为:
print(d.a) # returns object "a" - as desired
print(d.a) # returns 0 - second call returns the nested value
我不知道如何避免这种行为发生。除此之外,我还想生成一个强制维护数据结构的设置器。毫不奇怪,取消注释我上面写的 setter 也会产生意想不到的行为
d.a = {1} # ValueError: cannot change the data structure, expected dict got set - as desired
d.a.a = 2 # AttributeError: 'int' object has no attribute 'a'
d.a = 2
assert d.a == 0 and d['a'] == 2 # again unintended
我想了解我做错了什么,并使这项工作。还应该注意的是,我什至还没有考虑为nested_listof_dict 生成属性,这也是需要的。
解决方案
蒙克正是我需要的
推荐阅读
- java - 访问权限较低的具体类实现接口
- c - 在循环中重用结构(在 C 中)
- php - 为什么 laravel 在每个请求上创建令牌?
- ios - 如何在ios swift 3中录制视频时捕获图像
- sql - orainvalidnumbererrorin sql
- c# - 如何在 Linq 查询中将 where 条件放入 select 条件中
- javascript - 我无法在搜索页面中获取特定 URL
- c# - 如何将按钮放在选项卡旁边?
- bash - 使用 < 时如何隐藏文本输出
我使用 Vagrant 和自己编写的脚本来配置它。我的脚本之一包含以下代码:
mysql_secure_installation <<EOF y secret secret y y y y EOF
一切正常,但我想关闭到
vagrant up
日志- vb.net - 在 UWP 应用程序上首次尝试 SQlConnection.open 方法比桌面应用程序花费更长的时间