我必须将数据结构转换为对象。该数据结构可以由任意数量的嵌套列表和字典组成。我已经编写了当前能够执行此操作的代码,只要输入数据是最高级别的字典即可。如果输入数据是列表,那么这将不起作用,因为没有用于创建属性的初始键。如果输入数据是列表,我正在寻找的功能将使此类返回一个列表。
我当前的代码如下:
class DataConverter(object):
def __init__(self, data):
if isinstance(data, dict):
for key in data:
value = data[key]
if isinstance(value, list):
new_list = []
for ind in value:
if isinstance(ind, dict):
new_list.append(DataConverter(ind))
else:
new_list.append(ind)
setattr(self, key, new_list)
elif isinstance(value, dict):
setattr(self, key, DataConverter(value))
else:
setattr(self, key, value)
elif isinstance(data, list):
new_list = []
for val in data:
new_list.append(DataConverter(val))
# TODO: class needs to init as 'new_list' if it gets here
输入数据的结构与此类似,但更大、更深 1000 倍:
input_data = {
"foo": "bar",
"x": "y",
"Something": 12345,
"other": [
{
"yes": 1,
"no": 0
}
],
}
如果我要转换此数据,我希望像这样使用生成的对象:
>>> converted_data = DataConverter(input_data)
>>> converted_data.other[0].yes
1
当我获得如下结构的数据时,就会出现此问题:
input_data = [
{
"foo": "bar",
},
{
"x": "y",
},
{
"Something": 12345,
},
{
"other": [
{
"yes": 1,
"no": 0
}
]
}
]
我希望这些数据在转换后能够像这样使用:
>>> converted_data = DataConverter(input_data)
>>> converted_data[3].other[0].no
0
我开始编写一些我认为可行的东西,但如果输入是列表,我无法弄清楚如何将 DataConverter 对象初始化为列表对象。
回答
根据 JL Peyret 的回答,我添加了工厂方法并更改了一些代码以制作更好的版本。
class DataConverter(object):
def __init__(self, input_data):
if isinstance(input_data, dict):
for key, data in input_data.items():
if isinstance(data, dict):
setattr(self, key, DataConverter(data))
elif isinstance(data, list):
setattr(self, key, DataConverter.factory(data))
else:
setattr(self, key, data)
@classmethod
def factory(cls, data_input):
if isinstance(data_input, dict):
return DataConverter(data_input)
elif isinstance(data_input, list):
package = []
for part in package:
package.append(cls.factory(part))
return package
现在的预期用途
>>> obj = DataConverter.factory(input_data)
>>> obj[3].other[0].yes
1
最佳答案
我不会尝试对类 __init__
本身变得太聪明,而是使用工厂方法:
@classmethod
def factory(cls, data):
if isinstance(data, dict):
return cls(data)
elif isinstance(data, list):
res = []
for part in data:
res.append(cls(part))
return res
整个代码:
class DataConverter(object):
def __init__(self, data):
if isinstance(data, dict):
for key in data:
value = data[key]
if isinstance(value, list):
new_list = []
for ind in value:
if isinstance(ind, dict):
new_list.append(DataConverter(ind))
else:
new_list.append(ind)
setattr(self, key, new_list)
elif isinstance(value, dict):
setattr(self, key, DataConverter(value))
else:
setattr(self, key, value)
elif isinstance(data, list):
new_list = []
for val in data:
new_list.append(DataConverter(val))
# TODO: class needs to init as 'new_list' if it gets here
@classmethod
def factory(cls, data):
if isinstance(data, dict):
return cls(data)
elif isinstance(data, list):
res = []
for part in data:
res.append(cls(part))
return res
input_data = {
"foo": "bar",
"x": "y",
"Something": 12345,
"other": [
{
"yes": 1,
"no": 0
}
],
}
input_data_list = [
{
"foo": "bar",
},
{
"x": "y",
},
{
"Something": 12345,
},
{
"other": [
{
"yes": 1,
"no": 0
}
]
}
]
converted_data = DataConverter.factory(input_data)
print (f"{converted_data.other[0].yes=}")
converted_data_list = DataConverter.factory(input_data_list)
print(f"{converted_data_list[3].other[0].no=}")
和输出:
converted_data.other[0].yes=1
converted_data_list[3].other[0].no=0
关于python - 将类 init 作为列表对象或标准对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70717661/