我做错了什么(在 python 中通过重载实现替代相等)

发布于 2024-12-02 22:01:38 字数 722 浏览 0 评论 0原文

有人在 SO 上提出了一个问题,关于如何使用替代的相等函数在 python 中获取列表唯一函数。

我认为这可以通过从元素类继承并重载相等函数来完成,

import functools
@functools.total_ordering
class ffloat(float):
def __eq__(self,other):
    if floor(self) == floor(other):
        return True
    else:
        return False
def __le__(self,other):
    if self == other:
        return True
    else:
        return float(self) <= float(other)
def __hash__(self):
    return floor(self)


a = map(ffloat,[4.3,8,8.9, 13])


In [41]: a[1] == a[2]
Out[41]: True

但是

In [42]: set(a)
Out[42]: set([4.3, 8.0, 8.9, 13.0])

编辑:替换了abs < 1.5 平等与下限平等
添加了哈希值 PS 有一种方法可以用一个类和两个 lambda 来创建一个类工厂,并返回一个继承自第一个类的类,覆盖所需的相等函数。

A person asked a question on SO about how to get a list unique function in python with an alternative equality function.

I was thinking it could be done by inheriting from the element class and overloading the equality function

import functools
@functools.total_ordering
class ffloat(float):
def __eq__(self,other):
    if floor(self) == floor(other):
        return True
    else:
        return False
def __le__(self,other):
    if self == other:
        return True
    else:
        return float(self) <= float(other)
def __hash__(self):
    return floor(self)


a = map(ffloat,[4.3,8,8.9, 13])


In [41]: a[1] == a[2]
Out[41]: True

but

In [42]: set(a)
Out[42]: set([4.3, 8.0, 8.9, 13.0])

Edit: replaced abs < 1.5 equality with floor equality

Added Hash
P.S. is there a way to make a class factory out of this that a class and two lambda and returns a class that inherits from the first one overriding the needed equality function.

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

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

发布评论

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

评论(1

绝影如岚 2024-12-09 22:01:38

这不是一个有效的相等函数,因为它不是传递

mfloat(0) = = mfloat(1) == mfloat(2),但是mfloat(0) != mfloat(2)

另请注意,为了在集合中使用,您必须覆盖 __hash__ 以便以下属性适用于类的所有实例 a、b:

a == b ⇒ hash(a) == hash(b)

set 发现 hash(mfloat(8)) != hash(mfloat(9))。由于 set 假定上述属性成立,因此它会得出 mfloat(8) != mfloat(9) 的结论,而无需实际调用 __eq__


In summary, this works:

from math import floor
class ffloat(float):
    def __eq__(self,other):
        return floor(self) == floor(other):
    def __hash__(self):
        return floor(self)

a = map(ffloat,[4.3,8,8.9, 13])
print(set(a))
# output: {8.0, 4.3, 13.0}

This is not a valid equality function, since it's not transitive:

mfloat(0) == mfloat(1) == mfloat(2), but mfloat(0) != mfloat(2).

Also note that in order to be used in a set, you must override __hash__ so that the following property holds for all instances a, b of your class:

a == b ⇒ hash(a) == hash(b)

set finds out that hash(mfloat(8)) != hash(mfloat(9)). Since set assumes the above property holds, it concludes that mfloat(8) != mfloat(9) without actually calling __eq__.


In summary, this works:

from math import floor
class ffloat(float):
    def __eq__(self,other):
        return floor(self) == floor(other):
    def __hash__(self):
        return floor(self)

a = map(ffloat,[4.3,8,8.9, 13])
print(set(a))
# output: {8.0, 4.3, 13.0}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文