使用slots比较Python类的等价性
另一个问题提供了一个简单好用的方法来检查对象是否相等。我在这里重复一下这个答案,以便大家理解:
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__
的类中实现这个功能。我知道基类和子类都需要使用slots,但我该如何为这个类定义__eq__
,才能让它和slots一起正常工作呢?
2 个回答
1
杰夫,如果你需要跟踪这么多记录,建议你考虑使用“享元”设计模式。
可以参考这个链接:http://codesnipers.com/?q=python-flyweights
这个页面讲述了一种情况,很多被跟踪的记录有相同的值。在这种情况下,享元模式非常有用。不过,即使记录的值基本上是独一无二的,这个模式也同样适用。比如,你可以把这些值存储在一个numpy数组或矩阵里,然后用一个类来封装这些存储。
11
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
注意:要知道 __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'