如何更新 class 实例的历史字典属性并保持顺序?
How to update history dictionary attribute of a class instance and preserve order?
我是 class 编程新手。我试图将我的对象的初始属性(这是一个字典)保存在它的历史中,然后用属性的变化更新历史。代码下方:
import datetime
import pytz
class Property:
""" Simple property class """
@staticmethod
def _current_time():
utc_time = datetime.datetime.utcnow()
return pytz.utc.localize(utc_time)
def __init__(self, link, attributes):
self._link = link
self.__attributes = attributes
self._history = [(Property._current_time(), attributes)]
def update(self, new_attributes):
def dictdiff(d1, d2):
return dict(set(d2.items()) - set(d1.items()))
attr_change = dictdiff(self.__attributes, new_attributes)
self.__attributes.update(attr_change)
self._history.append((Property._current_time(), attr_change))
def show_attributes(self):
return self.__attributes
def show_history(self):
# how to show changes in time?
return self._history
prop = Property(1234, {"Price":3000, "Active":"Yes"})
prop.update({"Price":2500, "Active":"Yes"})
prop.update({"Active":"No"})
prop.show_history()
并输出:
Out[132]:
[(datetime.datetime(2018, 10, 28, 10, 24, 19, 712385, tzinfo=<UTC>),
{'Price': 2500, 'Active': 'No'}),
(datetime.datetime(2018, 10, 28, 10, 24, 19, 712385, tzinfo=<UTC>),
{'Price': 2500}),
(datetime.datetime(2018, 10, 28, 10, 24, 19, 712385, tzinfo=<UTC>),
{'Active': 'No'})]
历史上的第一项实际上应该是:
(datetime.datetime(2018, 10, 28, 10, 24, 19, 712385, tzinfo=<UTC>),
{"Price":3000, "Active":"Yes"})
我尝试了 this 但没有成功。似乎 init 函数正在随着属性的更新而更新初始化历史记录,同时在历史记录中首先我想看到第一次初始化的属性。
问题是您正在使用以下代码修改历史记录中的字典:
self.__attributes.update(attr_change)
你基本上是这样做的:
>>> attributes = {}
>>> history = [attributes]
>>> attributes.update(foo=3)
>>> history
[{'foo': 3}]
这可以通过在历史记录中存储字典的 副本 轻松解决:
self._history = [(Property._current_time(), attributes.copy())]
另见 How to copy a dictionary and only edit the copy。
您希望 第一个 历史条目是 attributes
.
的 副本
self._history = [(Property._current_time(), dict(attributes))]
正如您现在的代码一样,第一个历史条目 references current 属性字典。
我是 class 编程新手。我试图将我的对象的初始属性(这是一个字典)保存在它的历史中,然后用属性的变化更新历史。代码下方:
import datetime
import pytz
class Property:
""" Simple property class """
@staticmethod
def _current_time():
utc_time = datetime.datetime.utcnow()
return pytz.utc.localize(utc_time)
def __init__(self, link, attributes):
self._link = link
self.__attributes = attributes
self._history = [(Property._current_time(), attributes)]
def update(self, new_attributes):
def dictdiff(d1, d2):
return dict(set(d2.items()) - set(d1.items()))
attr_change = dictdiff(self.__attributes, new_attributes)
self.__attributes.update(attr_change)
self._history.append((Property._current_time(), attr_change))
def show_attributes(self):
return self.__attributes
def show_history(self):
# how to show changes in time?
return self._history
prop = Property(1234, {"Price":3000, "Active":"Yes"})
prop.update({"Price":2500, "Active":"Yes"})
prop.update({"Active":"No"})
prop.show_history()
并输出:
Out[132]:
[(datetime.datetime(2018, 10, 28, 10, 24, 19, 712385, tzinfo=<UTC>),
{'Price': 2500, 'Active': 'No'}),
(datetime.datetime(2018, 10, 28, 10, 24, 19, 712385, tzinfo=<UTC>),
{'Price': 2500}),
(datetime.datetime(2018, 10, 28, 10, 24, 19, 712385, tzinfo=<UTC>),
{'Active': 'No'})]
历史上的第一项实际上应该是:
(datetime.datetime(2018, 10, 28, 10, 24, 19, 712385, tzinfo=<UTC>),
{"Price":3000, "Active":"Yes"})
我尝试了 this 但没有成功。似乎 init 函数正在随着属性的更新而更新初始化历史记录,同时在历史记录中首先我想看到第一次初始化的属性。
问题是您正在使用以下代码修改历史记录中的字典:
self.__attributes.update(attr_change)
你基本上是这样做的:
>>> attributes = {}
>>> history = [attributes]
>>> attributes.update(foo=3)
>>> history
[{'foo': 3}]
这可以通过在历史记录中存储字典的 副本 轻松解决:
self._history = [(Property._current_time(), attributes.copy())]
另见 How to copy a dictionary and only edit the copy。
您希望 第一个 历史条目是 attributes
.
self._history = [(Property._current_time(), dict(attributes))]
正如您现在的代码一样,第一个历史条目 references current 属性字典。