[python] 속성별로 객체 인스턴스가 동일한 지 비교

나는 수업이 MyClass두 멤버 변수가 포함되어, foobar:

class MyClass:
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

나는에 대해 동일한 값을 가지고 각각의이 클래스의 두 인스턴스가 foo와를 bar:

x = MyClass('foo', 'bar')
y = MyClass('foo', 'bar')

그러나 동등성을 비교하면 Python은 False다음을 반환합니다 .

>>> x == y
False

파이썬 이이 두 객체를 동등하게 생각하게하려면 어떻게해야합니까?



답변

메소드를 구현해야합니다 __eq__.

class MyClass:
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

    def __eq__(self, other):
        if not isinstance(other, MyClass):
            # don't attempt to compare against unrelated types
            return NotImplemented

        return self.foo == other.foo and self.bar == other.bar

이제 출력합니다 :

>>> x == y
True

구현 __eq__하면 클래스의 인스턴스를 자동으로 해시 할 수 없게되므로 세트와 딕트에 저장할 수 없습니다. 불변 유형을 모델링하지 않는 경우 (예 : 속성 foobar 개체의 수명 내에서 값을 변경할 수 있음), 다음은 그냥 unhashable로 인스턴스를두고하는 것이 좋습니다.

불변 유형을 모델링하는 경우 datamodel 후크도 구현해야합니다 __hash__.

class MyClass:
    ...

    def __hash__(self):
        # necessary for instances to behave sanely in dicts and sets.
        return hash((self.foo, self.bar))

__dict__값 을 반복 하고 비교 하는 아이디어와 같은 일반적인 솔루션 은 권장되지 않습니다.__dict__ 비교할 수 없거나 해시 할 수없는 유형이 포함되어 .

NB : Python 3 이전에는 __cmp__대신 을 사용해야 할 수도 있습니다 __eq__. 파이썬 2 사용자는 __ne__불평등에 대한 합리적인 기본 행동 (즉, 평등 결과 반전)이 파이썬 2에서 자동으로 생성되지 않기 때문에 구현하기를 원할 수도 있습니다 .


답변

객체 의 리치 비교 연산자 를 재정의 합니다.

class MyClass:
 def __lt__(self, other):
      # return comparison
 def __le__(self, other):
      # return comparison
 def __eq__(self, other):
      # return comparison
 def __ne__(self, other):
      # return comparison
 def __gt__(self, other):
      # return comparison
 def __ge__(self, other):
      # return comparison

이처럼 :

    def __eq__(self, other):
        return self._id == other._id


답변

__eq__수업 에서 방법을 구현하십시오 . 이 같은:

def __eq__(self, other):
    return self.path == other.path and self.title == other.title

편집 : 객체가 동일한 인스턴스 사전이있는 경우에만 객체를 동일하게 비교하려면 다음을 수행하십시오.

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


답변

요약하자면 :

  1. python <= 2.0을 실행하는 경우를 제외하고 는 __eq__오히려 구현 하는 것이 좋습니다.__cmp____eq__ 2.1에서 추가됨)
  2. 또한 구현하는 것을 잊지 마십시오 __ne__( return not self.__eq__(other)또는return not self == other 매우 특별한 경우 제외 )
  3. 비교하려는 각 사용자 정의 클래스에서 연산자를 구현해야합니다 (아래 예 참조).
  4. None이 될 수있는 객체와 비교하려면 구현해야합니다. 통역사가 추측 할 수 없습니다 … (아래 예 참조)

    class B(object):
      def __init__(self):
        self.name = "toto"
      def __eq__(self, other):
        if other is None:
          return False
        return self.name == other.name
    
    class A(object):
      def __init__(self):
        self.toto = "titi"
        self.b_inst = B()
      def __eq__(self, other):
        if other is None:
          return False
        return (self.toto, self.b_inst) == (other.toto, other.b_inst)

답변

구체적인 경우에 따라 다음을 수행 할 수 있습니다.

>>> vars(x) == vars(y)
True

객체의 필드에서 파이썬 사전 보기


답변

Python 3.7의 데이터 클래스 사용 (위), 어떤지 객체 인스턴스의 비교는 붙박이 기능이다.

Dataclasses에 대한 백 포트는 파이썬 3.6 사용할 수 있습니다.

(Py37) nsc@nsc-vbox:~$ python
Python 3.7.5 (default, Nov  7 2019, 10:50:52)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from dataclasses import dataclass
>>> @dataclass
... class MyClass():
...     foo: str
...     bar: str
...
>>> x = MyClass(foo="foo", bar="bar")
>>> y = MyClass(foo="foo", bar="bar")
>>> x == y
True


답변

객체의 인스턴스를 비교할 때 __cmp__함수가 호출됩니다.

== 연산자가 기본적으로 작동하지 않으면 항상 __cmp__객체 의 기능을 재정의 할 수 있습니다 .

편집하다:

지적한 바와 같이이 __cmp__기능은 3.0부터 사용되지 않습니다. 대신 “풍부한 비교” 방법을 사용해야합니다 .