为什么这 2 个 python 类实例可以相互相等?

Why are these 2 python class instance could equal to each other?

提问人:anonNEWlearner 提问时间:10/2/2023 最后编辑:Matt HallanonNEWlearner 更新时间:10/2/2023 访问量:92

问:

from dataclasses import dataclass

@dataclass
class ThreeDPoint:
    x: int | float
    y = 0.0
    z: int | float = 0.0

point_1 = ThreeDPoint(1.0,2)

point_3 = ThreeDPoint(1,2)
print(point_1 == point_3)

结果是正确的。

我在python playground中运行了它。结果说这是真的。我认为这个数据类模块可能会在里面玩一些魔术,但我不确定到底发生了什么。

相等 python-dataclasses python-class

评论

6赞 Holloway 10/2/2023
是什么让你认为他们不应该平等?给你什么?1.0 == 1
0赞 John Gordon 10/2/2023
Python的设计者认为整数等于float。11.0
4赞 John Gordon 10/2/2023
另外,为什么这个问题被标记为 python 2.7?那时肯定不存在数据类......
2赞 Barmar 10/2/2023
另一个问题是重写操作,并通过比较属性来比较实例(类似于比较字典的方式)。dataclass==
0赞 ShadowRanger 10/2/2023
@JohnGordon:更不用说基本上所有语言的设计者都高于汇编级别。(保存像 Rust 这样类型严格要求的语言,它们只是禁止比较)

答:

0赞 Alba 10/2/2023 #1

在 Python 中,1.0 等于 1,因此将返回 true。 就像 Barmar 说的,当你比较数据类时,你是在比较使用它们的属性来比较实例,所以1.0 == 1

1.0 == 1是真的。

2 == 2是真的

因此,是真的。ThreeDPoint(1.0,2) == ThreeDPoint(1,2)

评论

0赞 anonNEWlearner 10/2/2023
谢谢,我是学习python的初学者。我以为一个是 int,另一个是浮点数,point_1或 3 返回一个包含不同类型数字的类,所以我认为这可能不相等,我对此感到困惑。现在全部清除,谢谢
0赞 Josef Joe Samanek 10/2/2023 #2

没有魔术。在 Python 中,整数 1 和浮点数 1.0 是相同的

> 1 == 1.0
True

另一方面,type(1) 与 type(1.0) 不同

> type(1) == type(1.0)
False

如果您希望相等运算符按照您建议的方式运行(= 当 x 具有相同的值但不同的类型时返回 False),那么您可以为类定义自己的相等方法,如下所示:

from dataclasses import dataclass


@dataclass
class ThreeDPoint:
    x: int | float
    y = 0.0
    z: int | float = 0.0

    def __eq__(self, other):
        for var, var_value in self.__dict__.items():
            try:
                other_var_value = getattr(other, var)
                if not (var_value == other_var_value and type(var_value) is type(other_var_value)):
                    return False
            except AttributeError:
                return False
        return True


point_1 = ThreeDPoint(1.0, 2)
point_3 = ThreeDPoint(1, 2)
print(point_1 == point_3)

评论

3赞 Guimoute 10/2/2023
嗯,你不需要遍历其他字典来定义“found”,你只需尝试获取属性并处理 KeyError。.other_var_value = getattr(other, var)
0赞 ShadowRanger 10/2/2023
更简单、更快速,无需循环(并正确使用 / 进行类型比较):在线尝试!isis not
0赞 Josef Joe Samanek 10/2/2023
你是对的家伙,@ShadowRanger,Guimoute,我写得很快,没有测试或检查太多。编辑了答案。感谢
1赞 ShadowRanger 10/2/2023
@JosefJoeSamanek:如果你想被提出来供你处理,请去掉第三个参数(返回而不是提出一个,如果任何属性可以合法地取值,可能会被误认为是正确的值)。AttributeErrorgetattrAttributeErrorFalse
0赞 Josef Joe Samanek 10/2/2023
谢谢,已修复(以前版本的遗留部分)