Tôi đã viết một mã để tối ưu hóa thiết kế bằng cách sử dụng thư viện Inspyred và việc thực hiện các thuật toán di truyền của nó. Về bản chất, quá trình tối ưu hóa tạo ra một số lượng lớn các biến thể trên một cấu trúc dữ liệu duy nhất, là một từ điển lồng nhau trong trường hợp của tôi.Từ điển Python chỉ lưu trữ các thay đổi
Để giảm lượng bộ nhớ được sử dụng trong quy trình, tôi đã cố tạo một loại loại từ điển khác biệt, chỉ lưu trữ các mục khác với từ điển cơ sở. Lý do cho điều này là trong một trường hợp điển hình, 95% dữ liệu trong cấu trúc dữ liệu sẽ không bị sửa đổi trong bất kỳ biến thể nào, nhưng bất kỳ phần nào của cấu trúc dữ liệu đều có thể chứa các biến thể. Vì vậy, vì lý do linh hoạt, tôi muốn có một kiểu dữ liệu hoạt động nhiều hơn hoặc ít hơn như một từ điển, nhưng chỉ lưu trữ các thay đổi.
Đây là kết quả của nỗ lực của tôi để tạo này:
#!/usr/bin/python
import unittest
import copy
global_base={}
class DifferentialDict(object):
"""
dictionary with differential storage of changes
all DifferentialDict objects have the same base dictionary
"""
def __init__(self,base=None):
global global_base
self.changes={}
if not base==None:
self.set_base(base)
def set_base(self,base):
global global_base
global_base=copy.deepcopy(base)
def __copy__(self):
return self
def __deepcopy__(self):
new=DifferentialDict()
new.changes=copy.deepcopy(self.changes)
return new
def get(self):
global global_base
outdict=copy.deepcopy(global_base)
for key in self.changes:
outdict[key]=self.changes[key]
return outdict
def __setitem__(self,key,value):
self.changes[key]=value
def __getitem__(self,key):
global global_base
if key in self.changes:
return self.changes[key]
else:
return global_base[key]
class TestDifferentialDict(unittest.TestCase):
def test1(self):
ldict={'a':{1:2,3:4},'b':{'c':[1,2,3],'d':'abc'}}
ddict=DifferentialDict(base=ldict)
self.assertEqual(ddict['a'],{1:2,3:4})
ddict['a']=5
self.assertEqual(ddict['a'],5)
def test2(self):
ldict={'a':{1:2,3:4},'b':{'c':[1,2,3],'d':'abc'}}
ddict1=DifferentialDict(base=ldict)
ddict2=DifferentialDict(base=ldict)
ddict1['a'][3]=5
ddict2['a'][3]=7
self.assertEqual(ddict1['a'][3],5)
self.assertEqual(ddict2['a'][3],7)
def test3(self):
ldict={'a':{1:2,3:4},'b':{'c':[1,2,3],'d':'abc'}}
ddict1=DifferentialDict(base=ldict)
ddict2=ddict1.__deepcopy__()
ddict1['a'][3]=5
ddict2['a'][3]=7
self.assertEqual(ddict1['a'][3],5)
self.assertEqual(ddict2['a'][3],7)
if __name__ == "__main__":
unittest.main()
Nó hoạt động tốt cho một cuốn từ điển đơn giản, nhưng bị phá vỡ khi từ điển mới sẽ được lồng vào trong từ điển chính. Tôi hiểu rằng điều này xảy ra bởi vì các từ điển cấp hai này là từ điển Python thực thay vì instantiations của DifferentialDict của tôi, dẫn đến ghi đè các mục trong global_base thay vì thay đổi trong self.changes. Tuy nhiên, họ phải là do tiền đề rằng tất cả các DifferentialDict instantiations chia sẻ cùng một từ điển cơ bản. Tôi có thể thêm một khóa 'cấp độ nhập cảnh' cho mỗi instantiationDict instantiation, nhưng cảm giác của tôi là có một giải pháp thanh lịch hơn mà eludes tôi.
Tôi thực sự đánh giá cao bất kỳ đề xuất nào về cách nhận từ điển vi phân hoạt động khi lồng nhau. Cảm ơn trước!
Bài kiểm tra nào đang trôi qua và bài kiểm tra nào không thành công? – RafaelC
Thử nghiệm 2 và 3 thất bại, 1 lần. –
Tôi vừa tìm thấy thư viện này: [dictdiffer] (https: // github.com/inveniosoftware/dictdiffer) có thể đã thực hiện nó. Trên Hacker News có một cuộc thảo luận về nó, nơi raymondh cho thấy làm thế nào để làm điều này với các từ điển không lồng nhau [trong Python tinh khiết] (https://news.ycombinator.com/item?id=5771696). –