Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检查赋值是否更改了目标对象的大多数python方法_Python_Python 3.x - Fatal编程技术网

检查赋值是否更改了目标对象的大多数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

我需要比较两个dict并使它们相等(分配a->b)。我还需要知道是否有任何值发生了变化,如果是这样,我需要运行一个计算代价高昂的函数。我想出了一些有效的代码,但它看起来一点也不像python

有没有更像蟒蛇的方法

   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。