我必須將資料結構轉換為物件。此資料結構可以包含任意數量的嵌套串列和字典。只要輸入資料是最高級別的字典,我已經撰寫了當前能夠執行此操作的代碼。如果輸入資料是一個串列,那么這將不起作用,因為沒有用于創建屬性的初始鍵。如果輸入資料是一個串列,我正在尋找的功能會讓這個類回傳一個串列。
我目前的代碼如下:
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
uj5u.com熱心網友回復:
我不會嘗試對類__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
uj5u.com熱心網友回復:
這行得通嗎?
我從串列中取出 subdicts 并將它們合并到一個更大的 dict 中,直到串列用完,然后我們DataConverter通過呼叫__init__我們新創建的 dict 的類來直接處理 dict。
elif isinstance(data, list):
new_data = {}
for subdict in data:
new_data.update(subdict)
self = self.__class__.__init__(self, new_data)
這很混亂,但很有效。如果有人有更好的解決方案(可能使用super()),我會全神貫注。
uj5u.com熱心網友回復:
我找到了一種半有效的方法,但它導致的解決方案并不完美。
class DataConverter(list):
def __init__(self, input_data):
if isinstance(input_data, dict):
for key, data in input_data.items():
if isinstance(data, list) or isinstance(value, dict):
setattr(self, key, DataConverter(value))
else:
setattr(self, key, value)
elif isinstance(input_data, list):
for val in data:
if isinstance(val, list) or isinstance(val, dict):
self.append(DataConverter(val))
else:
self.append(val)
這會產生一個物件,它是 lis 串列的串列串列……等等。如果資料不是串列,則每個串列都會添加屬性,但如果資料是串列,那么我們只需繼續串列。
唯一的缺點是現在這個物件的每一層都是一個串列,并且會有串列方法,但是由于我只是使用這個物件來讀取資料,它不應該成為一個障礙。
但是,我想知道是否有更好的方法,這對我來說似乎不是最好的方法,我相信其他對繼承有更好了解的人可以解決這個問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/411846.html
標籤:
上一篇:如何從類中的物件呼叫函式?
