Python中的通用__eq __()方法

时间:2018-03-09 15:48:12

标签: python python-3.x

我想为以下类创建一个通用的__eq__()方法。基本上我希望能够添加另一个属性(nick)而无需更改__eq__()

我想我可以通过迭代dir()以某种方式做到这一点,但我想知道是否有办法创建一个只提供属性的理解。

 class Person:
     def __init__(self, first, last):
         self.first=first
         self.last=last

     @property
     def first(self):
         assert(self._first != None)
         return self._first
     @first.setter
     def first(self,fn):
         assert(isinstance(fn,str))
         self._first=fn

     @property
     def last(self):
         assert(self._last != None)
         return self._last
     @last.setter
     def last(self,ln):
         assert(isinstance(ln,str))
         self._last=ln
     @property
     def full(self):
         return f'{self.first} {self.last}'

     def __eq__(self, other):
         return self.first==other.first and self.last==other.last

 p = Person('Raymond', 'Salemi')
 p2= Person('Ray', 'Salemi')

3 个答案:

答案 0 :(得分:7)

您可以使用__dict__来检查所有属性是否相同,以及所有属性的缩放:

如果对象不匹配类型,我只需返回False

class Person:
    def __init__(self, first, last, nick):
        self.first = first
        self.last = last
        self.nick = nick

    def __eq__(self, other):
        return self.__dict__ == other.__dict__  if type(self) == type(other) else False

>>> p = Person('Ray', 'Salemi', 'Ray')
>>> p2= Person('Ray', 'Salemi', 'Ray')
>>> p3 = Person('Jared', 'Salemi', 'Jarbear')

>>> p == p2
True
>>> p3 == p2
False
>>> p == 1
False

答案 1 :(得分:2)

您可以使用以下结构获取Class的所有属性:

from itertools import chain
@classmethod
def _properties(cls):
    type_dict = dict(chain.from_iterable(typ.__dict__.items() for typ in reversed(cls.mro())))
    return {k for k, v in type_dict.items() if 'property' in str(v)}

__eq__会变成这样:

def __eq__(self, other):
    properties = self._properties() & other._properties()
    if other._properties() > properties and self._properties() > properties:
        # types are not comparable
        return False
    try:
        return all(getattr(self, prop) == getattr(other, prop) for prop in properties)
    except AttributeError:
        return False

使用reversed(cls.mro())的原因是这样的:

class Worker(Person):
    @property
    def wage(self):
        return 0

p4 = Worker('Raymond', 'Salemi')

print(p4 == p3)
True

答案 2 :(得分:-1)

你可以尝试这样做,如果你想在dict中设置eq并设置

,它也会工作
def __eq__(self, other):
    """Overrides the default implementation"""
    if isinstance(self, other.__class__):
        return self.__hash__() == other.__hash__()

    return NotImplemented

def __hash__(self):
    """Overrides the default implementation,
       and set which fieds to use for hash generation
    """
    __make_hash = [
         self.first
    ]
    return hash(tuple(sorted(list(filter(None, __make_hash)))))