检查赋值是否更改了目标对象的大多数python方法
我需要比较两个dict并使它们相等(分配a->b)。我还需要知道是否有任何值发生了变化,如果是这样,我需要运行一个计算代价高昂的函数。我想出了一些有效的代码,但它看起来一点也不像python 有没有更像蟒蛇的方法检查赋值是否更改了目标对象的大多数python方法,python,python-3.x,Python,Python 3.x,我需要比较两个dict并使它们相等(分配a->b)。我还需要知道是否有任何值发生了变化,如果是这样,我需要运行一个计算代价高昂的函数。我想出了一些有效的代码,但它看起来一点也不像python 有没有更像蟒蛇的方法 def sync_data(activity_update_response, existing_quote): data_changed = False if activity_update_response["source"]["firstNa
def sync_data(activity_update_response, existing_quote):
data_changed = False
if activity_update_response["source"]["firstName"] != existing_quote["origin"]["applicant"]["firstName"]:
activity_update_response["source"]["firstName"] = existing_quote["origin"]["applicant"]["firstName"]
data_changed = True
if activity_update_response["source"]["lastName"] != existing_quote["origin"]["applicant"]["surname"]:
activity_update_response["source"]["lastName"] = existing_quote["origin"]["applicant"]["surname"]
data_changed = True
# ( ... )
# repeat for 4 more fields
if data_changed:
# this is slow
recalculate_hashes(activity_update_response)
我认为将变量存储在
data\u changed
中是一个非常好的方法。我认为这看起来不像蟒蛇的原因是你在重复自己(不是干的)
我还没有测试过这一点,但是你可以试着沿着这条线做更多的事情
def同步数据(活动更新响应,现有报价):
数据更改=错误
原产地=现有报价[“原产地”][“申请人”]
源=活动\更新\响应[“源”]
对于中的字段(“firstName”、“lastName”):#再扩展4个字段
数据更改=数据更改或原点[字段]!=来源[字段]
源[字段]=源[字段]
如果数据更改:
#这太慢了
重新计算散列(活动更新响应)
为了使代码更具可读性,我建议:
def sync_data(activity_update_response, existing_quote):
Fields = ("firstName", "lastName", )# add 4 more fields
for field in Fields:
if activity_update_response["source"][field] != existing_quote["origin"]["applicant"][field]
activity_update_response["source"].update({f: existing_quote["origin"]["applicant"][f] for f in Fields})
recalculate_hashes(activity_update_response)
break
我看不出还有更多的重构要做,因为这基本上就是您要做的。收集要更新的密钥,然后更新dict并重新计算哈希值。Python3.8中新的赋值表达式操作符很方便
def sync_data(activity_update_response, existing_quote):
# XXX Pick good names
a = activity_update_response["source"]
e = existing_quote["origin"]["applicant"]
fields = ["lastName", "firstName", ...]
#if (keys_to_update := [x for x in fields if a[x] != e[x]]):
keys_to_update = [x for x in fields if a[x] != e[x]]
if keys_to_update:
recalculate_hashes(activity_update_response)
for key in keys_to_update:
a[key] = e[key]
您可以创建一个自定义字典类,该类知道是否已更改:
class DictThatKnowsIfItChanged(dict):
def __setitem__(self, key, value):
self.data_changed = True
super().__setitem__(key, value)
def reset_data_changed(self):
self.data_changed = False
并将其用于可变活动更新响应。您还可能希望重载update
方法
派生一个标准类来满足您的需要是相当复杂的
# it is good idea to define it in outside scope as it does never change
Fields = ("firstName", "lastName", ) # add 4 more fields
def sync_data(activity_update_response, existing_quote):
update_dict = {field: existing_quote["origin"]["applicant"][field] for field in Fields if activity_update_response["source"][field] != existing_quote["origin"]["applicant"][field]}
# or use get if some of the keys might not be available, example:
update_dict = {field: existing_quote["origin"]["applicant"][field] for field in Fields if activity_update_response["source"].get(field, None) != existing_quote["origin"]["applicant"].get(field, None)}
if update_dict:
activity_update_response["source"].update(update_dict )
recalculate_hashes(activity_update_response)
考虑使用代码中描述的get(它非常简单,可以保护代码免受不必要的异常)。
我会更进一步地使用这段代码,并这样编写:
FieldsToCheck = ("firstName", "lastName", ) # add 4 more fields
def sync_data(dict_1, dict_2): # change name of arguments
# or use get if some of the keys might not be available, example:
change = {field: dict_2[field] for field in FieldsToCheck if dict_1[field] != dict_2[field]}
if change :
dict_1.update(change)
recalculate_hashes(activity_update_response)
# to execute this function pass folowing parameters:
sync_data(activity_update_response["source"], existing_quote["origin"]["applicant"])
为什么要这样做?处理简单的数据,使您的代码易于理解。那么您想将两者合并吗
new_dict={**a,**b}
首先更改dict的代码不能按要求触发昂贵的函数有什么原因吗?如果firstName和lastName(以及其他字段)是唯一的键,您可以将检查减少为一个:“If activity_update_response[“source”!=existing_quote[“origin”][“applicator””(但不要以同样的方式减少分配).@Torxed,如果第一个字典中没有更改,我想避免运行重新计算哈希。这些不是唯一的键,还有更多。而且我想在最后重新计算哈希,所以我只做一次。data\u changed=data\u changed或…
;一旦它变为True,您不想将其重置为False
de>。我认为其中一个字段来自dict中的不同路径,因此我可能无法在for循环中完成所有操作,但我将为其他字段尝试此操作。感谢此操作与原始代码的操作不同;这将在第一次更改时重新计算哈希值,并忽略其余字段。目标是更新所有字段,然后n如果任何字段发生更改,请重新计算哈希值。它的作用与原始代码完全相同。先生,请阅读原始问题。顺便说一句,我在编辑模式下没有更新字段,所以做了#todo注释。看起来只有选中的字段才应该更新。不,没有。使用中断,lastName
不会更新如果firstName
为,则会更新。OP会更新所有不同的字段,无论哪些字段已经更新,然后在指示的情况下重新计算一次。这难道不会多次计算重新计算散列()吗?此处:activity\u update\u response[“source”]。更新({f:existing_quote[“origin”][“applicator”][f]对于f in Fields})
所有字段都会更新。我重构了一些名称,因为它们太过描述性,无法放在这里使用。这在Python3.6.8的烧瓶容器中使用,这个赋值运算符不在该版本中吗?不;正如我所说,它是Python3.8的新名称(仍处于测试阶段)。这实际上只是一个优化;我将使用当前有效的代码进行更新。看起来他只想跟踪少数字段,因此需要额外的“if”语句。哦,因此需要一个self.keys\u I\u want\u to\u track
列表,以及self.data\u changed=键入self.keys\u I\u want\u to\u track
而不是True。