使用插槽的Python类的相等性

时间:2010-12-23 21:30:50

标签: python class equality slots

另一个question提供了一个很好的,简单的解决方案,用于实现对象相等的测试。我将重复上下文的答案:

class CommonEqualityMixin(object):

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

    def __ne__(self, other):
        return not self.__eq__(other)

class Foo(CommonEqualityMixin):

    def __init__(self, item):
        self.item = item

我想为使用__slots__的课程执行此操作。我知道基类和子类都必须使用插槽,但是如何定义__eq__以便使用插槽?

2 个答案:

答案 0 :(得分:6)

import operator

class CommonEqualityMixin(object):

    __slots__ = ()

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            if self.__slots__ == other.__slots__:
                 attr_getters = [operator.attrgetter(attr) for attr in self.__slots__]
                 return all(getter(self) == getter(other) for getter in attr_getters)

        return False

    def __ne__(self, other):
        return not self.__eq__(other)

使用示例:

class Foo(CommonEqualityMixin):
    __slots__ = ('a', )
    def __init__(self, a):
        self.a = a

Foo(1) == Foo(2)
# False
Foo(1) == Foo(1)
# True

N.B:请注意,__slots__没有得到继承它不像__dict__所以如果新的类FooBar继承自Foo,上面的代码将不起作用

示例:

class FooBar(Foo):
    __slots__ = ('z')
    def __init__(self, a, z):
        self.z = z
        super(FooBar, self).__init__(a)

FooBar(1, 1) == FooBar(2, 1)
# True

print FooBar(1, 1).__slots__
# 'z'

答案 1 :(得分:1)

杰夫,如果你需要跟踪那么多记录,你应该考虑使用Flyweight设计模式。

请参阅:http://codesnipers.com/?q=python-flyweights

该页面描述了许多跟踪记录具有相同值的情况。在这种情况下,Flyweight模式非常有用。但是,当记录具有有效的唯一值时,它也非常有用。 (在这种情况下,您将值存储在numpy数组/矩阵等中,并将存储包装在类中)。