检查两个对象是否是彼此的深层副本的快速方法

问题描述 投票:0回答:2

假设我有某个类的两个对象,并且想要确保它们是深拷贝而不仅仅是浅拷贝。

下面的代码检查是否可以使用

is
来确定它们是否是深拷贝。

import copy

class MyClass():
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
          
mylist = [1,2,3,4]        
        
obj1 = MyClass(1,2,mylist)

obj2 = copy.copy(obj1)
print("obj2 is obj1: {}, obj2.c is obj1.c: {}".format(obj2 is obj1, obj2.c is obj1.c))

obj3 = copy.deepcopy(obj1)
print("obj3 is obj1: {}, obj3.c is obj1.c: {}".format(obj3 is obj1, obj3.c is obj1.c))

输出符合预期:

"obj2 is obj1: False, obj2.c is obj1.c: True"
"obj3 is obj1: False, obj3.c is obj1.c: False"

我们看到,如果我们使用

is
来比较对象的字段,而不仅仅是对象本身,则它仅适用于检查深层副本。

我的问题是是否有更简单的方法来检查这一点。我想对不同类的实例进行此检查,即它应该可以工作而不必指定对象的字段是什么样的。我想最终得到一个看起来有点像这样的函数:

def is_deep_copy(obj1, obj2):
    if "[stuff to determine if they are deep copies]":
        return True
    else:
        return False
python object copy
2个回答
0
投票

这里似乎已经有了答案:Comparing Python objects from deepcopy

他们提到了几个答案:

1.

def deep_compare(left, right, excluded_keys = []):
# convert left and right to dicts if possible, skip if they can't be converted
try: 
    left = left.__dict__
    right = right.__dict__
except:
    pass

# both sides must be of the same type 
if type(left) != type(right):
    return False

# compare the two objects or dicts key by key
if type(left) == dict:
    for key in left:
        # make sure that we did not exclude this key
        if key not in excluded_keys:
            # check if the key is present in the right dict, if not, we are not equals
            if key not in right:
                return False
            else:
                # compare the values if the key is present in both sides
                if not deep_compare(left[key], right[key], excluded_keys):
                    return False

    # check if any keys are present in right, but not in left
    for key in right:
        if key not in left and key not in excluded_keys:
            return False
    
    return True

# check for each item in lists
if type(left) == list:
    # right and left must have the same length
    if len(left) != len(right):
        return False

    # compare each item in the list
    for index in range(len(left)):
        if not deep_compare(left[index], right[index], excluded_keys):
            return False

# do a standard comparison
return left == right
  1. def deep_compare(左,右): 尝试: 如果没有留下。dict: 返回左==右

      for key in left.__dict__:
          if key not in right.__dict__:
              return false
          else:
              return deep_compare(left[key], right[key])
    

    除了(属性错误,类型错误): 返回左==右

import logging
log = logging.getLogger(__name__)
def deep_compare(self,left, right, level=0):
    if type(left) != type(right):
        log.info("Exit 1 - Different types")
        return False

    elif type(left) is dict:
        # Dict comparison
        for key in left:
            if key not in right:
                log.info("Exit 2 - missing {} in right".format(key))
                return False
            else:
                if not deep_compare(left[str(key)], right[str(key)], level +1 ):
                    log.info("Exit 3 - different children")
                    return False
        return True
    elif type(left) is list:
        # List comparison
        for key in left:
            if key not in right:
                log.info("Exit 4 - missing {} in right".format(key))
                return False
            else:
                if not deep_compare(left[left.index(key)], right[right.index(key)], level +1 ):
                    log.info("Exit 5 - different children")
                    return False
        return True
    else:
        # Other comparison
        return left == right

    return False

0
投票

基于您的示例代码

class MyClass():
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, self.__class__):
            return False
        
        return (self.a, self.b, self.c) == (other.a, other.b, other.c)

请注意,如果类的属性本身不是原始类型,则它们还必须实现自己版本的

__eq__
方法。

如果不是这种情况,将进行表面检查。

© www.soinside.com 2019 - 2024. All rights reserved.