有没有办法检查两个对象在 python 中的每个变量中是否包含相同的值?

发布于 2024-11-16 08:02:38 字数 535 浏览 4 评论 0原文

如何检查 a 的两个实例是否

class FooBar(object):
    __init__(self, param):
        self.param = param
        self.param_2 = self.function_2(param)
        self.param_3 = self.function_3()

相同?我所说的相同是指它们的所有变量都具有相同的值。

a = FooBar(param)
b = FooBar(param)

我想到

if a == b:
    print "a and b are identical"!

这样可以没有副作用吗?

我的问题的背景是单元测试。我想实现类似的目标:

self.failUnlessEqual(self.my_object.a_function(), another_object)

How do I check if two instances of a

class FooBar(object):
    __init__(self, param):
        self.param = param
        self.param_2 = self.function_2(param)
        self.param_3 = self.function_3()

are identical? By identical I mean they have the same values in all of their variables.

a = FooBar(param)
b = FooBar(param)

I thought of

if a == b:
    print "a and b are identical"!

Will this do it without side effects?

The background for my question is unit testing. I want to achieve something like:

self.failUnlessEqual(self.my_object.a_function(), another_object)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

两仪 2024-11-23 08:02:38

如果您希望 == 工作,请在类中实现 __eq__ 方法来执行丰富比较。

如果您只想比较所有属性的相等性,则可以通过比较每个对象中的__dict__来简洁地做到这一点:

class MyClass:

    def __eq__(self, other) : 
        return self.__dict__ == other.__dict__

If you want the == to work, then implement the __eq__ method in your class to perform the rich comparison.

If all you want to do is compare the equality of all attributes, you can do that succinctly by comparison of __dict__ in each object:

class MyClass:

    def __eq__(self, other) : 
        return self.__dict__ == other.__dict__
疯狂的代价 2024-11-23 08:02:38

对于 python 3.7 及以上版本,您还可以使用 dataclass 来轻松检查您想要的内容。例如:

from dataclasses import dataclass

@dataclass
class FooBar:
    param: str
    param2: float
    param3: int

a = Foobar("test_text",2.0,3)
b = Foobar("test_text",2.0,3)

print(a==b)

将返回 True

For python 3.7 onwards you can also use dataclass to check exactly what you want very easily. For example:

from dataclasses import dataclass

@dataclass
class FooBar:
    param: str
    param2: float
    param3: int

a = Foobar("test_text",2.0,3)
b = Foobar("test_text",2.0,3)

print(a==b)

would return True

淡淡の花香 2024-11-23 08:02:38

对于任意对象,== 运算符仅在两个对象是同一对象(即,如果它们引用内存中的相同地址)时返回 true。

为了获得更多“定制”行为,您需要覆盖丰富的比较运算符,在本例中特别是 __eq__。尝试将其添加到您的类中:(

def __eq__(self, other):
    if self.param == other.param \
    and self.param_2 == other.param_2 \
    and self.param_3 == other.param_3:
        return True
    else:
        return False

可以在此处整理所有参数的比较,但为了清楚起见,我将它们保留在其中)。

请注意,如果参数本身就是您定义的对象,则这些对象必须以类似的方式定义 __eq__ 才能正常工作。

另一点需要注意的是,如果您尝试按照我上面所做的方式将 FooBar 对象与另一种类型的对象进行比较,python 将尝试访问另一种类型对象的 param、param_2 和 param_3 属性,这将抛出属性错误。您可能需要首先使用 isinstance(other, FooBar) 检查要比较的对象是否是 FooBar 的实例。默认情况下不会这样做,因为在某些情况下您可能希望返回 True 以进行不同类型之间的比较。

请参阅 AJ 的答案,了解一种更简洁的方法,可以简单地比较也不应引发属性错误的所有参数。

有关丰富比较的更多信息,请参阅Python 文档

For an arbitrary object, the == operator will only return true if the two objects are the same object (i.e. if they refer to the same address in memory).

To get more 'bespoke' behaviour, you'll want to override the rich comparison operators, in this case specifically __eq__. Try adding this to your class:

def __eq__(self, other):
    if self.param == other.param \
    and self.param_2 == other.param_2 \
    and self.param_3 == other.param_3:
        return True
    else:
        return False

(the comparison of all params could be neatened up here, but I've left them in for clarity).

Note that if the parameters are themselves objects you've defined, those objects will have to define __eq__ in a similar way for this to work.

Another point to note is that if you try to compare a FooBar object with another type of object in the way I've done above, python will try to access the param, param_2 and param_3 attributes of the other type of object which will throw an AttributeError. You'll probably want to check the object you're comparing with is an instance of FooBar with isinstance(other, FooBar) first. This is not done by default as there may be situations where you would like to return True for comparison between different types.

See AJ's answer for a tidier way to simply compare all parameters that also shouldn't throw an attribute error.

For more information on the rich comparison see the python docs.

冷心人i 2024-11-23 08:02:38

根据 Lutz 的 Learning Python,“==”运算符测试值的等价性,递归地比较所有嵌套对象。 “is”运算符测试两个对象是否是同一个对象,即内存中的相同地址(相同的指针值)。
除了小整数和简单字符串的缓存/重用之外,两个对象如 x = [1,2] 和 y = [1,2] 在值上是相等的“==”,但是y“是”x< /em> 返回 false。对于两个浮点数 x = 3.567 和 y = 3.567 也是如此。这意味着它们的地址不同,或者换句话说,hex(id(x)) != hex(id(y))。

对于类对象,我们必须重写方法 __eq__() 来创建两个 A 类对象,例如 x = A(1,[2,3]) 和 y = A(1,[2,3]) “==”内容。默认情况下, class object "==" 会比较 id在这种情况下,只有 id(x) != id(y),所以 x != y。
总之,如果 x“是”y,则 x == y,但反之则不然。

According to Learning Python by Lutz, the "==" operator tests value equivalence, comparing all nested objects recursively. The "is" operator tests whether two objects are the same object, i.e. of the same address in memory (same pointer value).
Except for cache/reuse of small integers and simple strings, two objects such as x = [1,2] and y = [1,2] are equal "==" in value, but y "is" x returns false. Same true with two floats x = 3.567 and y = 3.567. This means their addresses are different, or in other words, hex(id(x)) != hex(id(y)).

For class object, we have to override the method __eq__() to make two class A objects like x = A(1,[2,3]) and y = A(1,[2,3]) "==" in content. By default, class object "==" resorts to comparing id only and id(x) != id(y) in this case, so x != y.
In summary, if x "is" y, then x == y, but opposite is not true.

败给现实 2024-11-23 08:02:38

如果这是您想在测试中使用的东西,您只想验证简单对象的字段是否相等,请查看 与 testfixtures 比较

from testfixtures import compare

compare(a, b)

If this is something you want to use in your tests where you just want to verify fields of simple object to be equal, look at compare from testfixtures:

from testfixtures import compare

compare(a, b)
歌枕肩 2024-11-23 08:02:38

为了避免向模型添加或删除属性并忘记对 __eq__ 函数进行适当的更改,您可以按如下方式定义它。

def __eq__(self, other):
    if self.__class__ == other.__class__:
        fields = [field.name for field in self._meta.fields]
        for field in fields:
            if not getattr(self, field) == getattr(other, field):
                return False
        return True
    else:
        raise TypeError('Comparing object is not of the same type.')

这样,所有的对象属性就被比较了。现在,您可以使用 object.__eq__(other)object == other 检查属性相等性。

To avoid the possibility of adding or removing attributes to the model and forgetting to do the appropriate changes to your __eq__ function, you can define it as follows.

def __eq__(self, other):
    if self.__class__ == other.__class__:
        fields = [field.name for field in self._meta.fields]
        for field in fields:
            if not getattr(self, field) == getattr(other, field):
                return False
        return True
    else:
        raise TypeError('Comparing object is not of the same type.')

In this way, all the object attributes are compared. Now you can check for attribute equality either with object.__eq__(other) or object == other.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文